What methods are available to generate dynamic shapes using HTML?

Looking to create an interactive triangle where users can move vertices or sides, updating angles in real-time. I'm struggling with how to accomplish this task. My initial attempt was to manually draw the triangle using the code below.

<!DOCTYPE html>
<html>
<head>
    <title>Triangle Canvas Example</title>
</head>
<body>
    <canvas id="myCanvas" width="700" height="700"></canvas>

    <script>
    var canvasElement = document.querySelector("#myCanvas");
    var context = canvasElement.getContext("2d");

    
    // Code for drawing circles and labels

    
    
    // Drawing the triangle
    


    

    </script>

</body>
</html>

To see the resulting image, click here.

The issue lies in my hardcoded approach - static values for angles, circles, and the triangle itself. I'm stuck on how to transform this into a dynamic element. Research hasn't provided any solutions, so any guidance, whether through a video tutorial or article, would be highly appreciated.

Answer №1

A dynamic triangle was successfully created even without a strong mathematical background. Hopefully, this solution proves to be helpful for your needs.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Triangle</title>
    
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        
        canvas {
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    
    <canvas width="500" height="500"></canvas>
    
    <script>
        let mousePosition = [0, 0];
        let mouseClicked = false;
        let dragged = null;

        const getMousePosition = (canvas, event) => {
            const rect = canvas.getBoundingClientRect();
            const x = Math.min(Math.max(event.clientX - rect.left, 0), canvas.width);
            const y = Math.min(Math.max(event.clientY - rect.top, 0), canvas.width);

            return [x, y];
        }

        document.addEventListener('DOMContentLoaded', () => {
            const canvas = document.querySelector('canvas');
            const ctx = canvas.getContext('2d');

            document.addEventListener('mousemove', (event) => {
                mousePosition = getMousePosition(canvas, event);
            });

            document.addEventListener('mousedown', () => mouseClicked = true); 
            document.addEventListener('mouseup', () => mouseClicked = false); 
            
            const points = [
                [50, 200, '#f00'],
                [150, 50, '#0f0'],
                [200, 150, '#00f'],
            ];
            
            const radius = 10;
            
            const draw = () => {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                const [mX, mY] = mousePosition;
                
                for (const [index, [x, y, color]] of points.entries()) {
                    const hovered = (mX - x) ** 2 + (mY - y) ** 2 < radius ** 2;
                    const style = hovered ? 'fill' : 'stroke';

                    ctx.beginPath();
                    ctx.arc(x, y, radius, 0, Math.PI * 2, true); // Outer circle
                    
                    ctx[`${style}Style`] = color;
                    ctx[style]();
                    
                    if(hovered && mouseClicked) {
                        dragged = index;
                    }
                    
                    if(dragged === index) {
                        points[index] = [...mousePosition, color];
                        
                        if(!mouseClicked) dragged = null;
                    }
                }
                
                ctx.beginPath();
                ctx.moveTo(points[0][0], points[0][1]);
                ctx.lineTo(points[1][0], points[1][1]);
                ctx.lineTo(points[2][0], points[2][1]);
                ctx.lineTo(points[0][0], points[0][1]);
                ctx.strokeStyle = '#000';
                ctx.stroke();

                window.requestAnimationFrame(draw);
            }
            
            window.requestAnimationFrame(draw);
        });
    </script>
</body>
</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Numbering each numeral

Looking to add a sequence number next to each digit using jQuery or JavaScript: If I enter the following numbers: 1, 1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 8, 9, 10 and so on then the desired output should be: 1.1, 1.2, 1.3, 2.1, 3.1, 4.1, 5.1, 5.2, 5.3, 6.1 ...

How to Properly Manipulate DOM Elements in an Angular Directive

My directive, powerEntry, has different CSS classes that I want to add or remove based on the model state. Currently, in my link function, I have some logic like this: Script.JS if (calcState.availablePoints > 0 && isHighEnoughLevel) { ...

My handleChange function is inaccessible to the event listener

ParentComponent.js (App.js) import React from "react"; import ChildComponent from "./ChildComponent"; import data from "./data"; import "./styles.css"; class ParentComponent extends React.Component { constructor() ...

What is the best way to store the JSON data that is returned in a JavaScript function as a variable

My goal is to save the client's IP address in a variable after fetching it in JSON format from api.ipify.org. I have managed to display the IP if I alert the result, but I am struggling to store it in a variable. This code snippet works: <script& ...

AngularJS Setting Default Values in HTML Pages

My goal is to set the default value for a dropdown in an Angular HTML Page. The page uses tabs, and I want the default value to load when a specific tab is clicked. <div class="col-md-9" ng-cloak ng-controller="ServiceTypeController"> <md-conten ...

Align the center of table headers in JavaScript

I'm currently in the process of creating a table with the following code snippet: const table = document.createElement('table'); table.style.textAlign = 'center'; table.setAttribute('border', '2'); const thead ...

Preventing automatic recompilation in Angular when there are changes in the assets folder

I am facing an issue while attempting to download a file generated from a Spring Boot application in the assets folder of an Angular project. Every time I call the Spring API from Angular services, the Angular CLI recompiles the project after creating the ...

Error message: The function send() cannot be applied to the object received by request.post() in Node

As I embark on testing the functionalities of my node.js website using chai and mocha, I encountered an issue when running npm test. The error message displayed is: ' TypeError: request.post(...).send is not a function' Referencing the code sni ...

Is it required for IDs in CSS to always correspond to a single element? How should IDs be handled if the same element is repeated multiple times on

Is it possible to have a menu that is visible at both the top and bottom of an extensive HTML page using the following code: <div id="menu"><ul><li>Home</li><li>About</li></ul></div> Would it be appropriate ...

The issue of req.files being undefined in Express.js

I am aiming to upload files to s3 without depending on any middleware like multer. Below is the code snippet of my approach: <form role="form" action="/send" method="post"> <input type="file" name="photo" class="form-control"/> <button ...

NEXT JS - Application renders twice due to rewrites in place

I'm currently working on a NEXT JS project and facing the issue of the app rendering twice! Challenge After implementing rewrites in next.config.js, the app is being rendered twice. Removing the rewrites solves the issue and only renders once. next ...

Creating a regular expression to capture a numerical value enclosed by different characters:

export interface ValueParserResult { value: number, error: string } interface subParseResult { result: (string | number) [], error: string } class ValueParser { parse(eq: string, values: {[key: string] : number}, level?: number) : ValueParse ...

Achieving responsive masonry layout with Bootstrap 4

I'm attempting to implement the bootstrap 4 masonry effect on my website, but I'm facing issues with card responsiveness. The page is very basic without any special effects. While the page works well when resizing the browser window, it doesn&ap ...

Verifying CSS updates with Capybara detection

I'm in the process of developing a web application that dynamically changes its CSS styles based on user input. Everything is working smoothly, but I'm facing an issue with my automated tests not confirming whether the CSS updates are actually ta ...

Is there a way to select and handle multiple elements using async wdio with the same selector?

My test scenario involves using async wdio to test my React app, where I need to count elements with a specific selector and check their contents. The code snippet being tested is as follows: <div className='container'> <li className= ...

Calculating the size of grid thumbnails or items using the calc() function

I am currently working on building a responsive portfolio grid that spans the full width of the screen. To achieve this, I have set the width of the items using calc() and ensured that the thumbnail image fills the entire div by applying the following CSS: ...

Retrieve the values and IDs for every span element within the form

I have been attempting to retrieve all span elements within a form and make them editable input text fields. Once you click away, they should revert back to span elements. I will provide a live example in the attached fiddle. I tried my hand at it, but the ...

Placing numerous meshes that are mostly alike but not exactly the same in a scene

We utilize a single geometry that is attached to every mesh within our scene. var geometry = new three.PlaneGeometry(1, 1, 1, 1), Each object has a texture that is generated and cached to form a new material and a mesh for the object. this.material = ne ...

Issue with routing in a bundled Angular 2 project using webpack

Having a simple Angular application with two components (AppComponent and tester) webpacked into a single app.bundle.js file, I encountered an issue with routing after bundling. Despite trying various online solutions, the routing feature still does not wo ...

How to implement a for loop within a Vue.js method

Within Vuejs, I have a method that updates multiple variables based on user selection. methods: { updateChart(){ this.chart1.series[1].data = [this.$store.state.selectedcities[0].value[1]]; this.chart1.series[2].data = [this.$store.state.selecte ...