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

What are the ways to activate an element in vue js?

Is there a way to modify the code so that the function triggers with just one click instead of two? export default { methods: { remove(){ $('.remove-me button').click( function() { removeItem(this); }); ...

JavaScript - incorrect order for compiling

Is the user already in my SQLite database? If the user exists: return 500 (ERROR!!) If the user does not exist: return 200 (OK) This is my Node.js + Express script running on the server side. app.post('/adduser', function(req, res){ db.se ...

Modifying Selectize Ajax data in real-time

How can the student_id be changed each time the modal is opened? This is the code: $('#relationshipModal input[name=existing_user]').selectize({ valueField: 'id', searchField: 'name', options: [], create: fal ...

Exploring the intricacies of React's useEffect: Solving the challenge of updating data when two separate dependency arrays are

I am facing an issue with two different useEffect hooks where the dependency arrays are different. const [dateFilterSort, setDateFilterSort] = useState({ queryText: initialQueryText(params.sortName), cardText: initialCardText(params.sortName), ...

Is there a way to divide text in half while preserving the HTML structure?

I am in need of setting up an RSS feed where only a portion (or a specified number of characters) of the article's text is displayed, while keeping all HTML tags intact (such as images or YouTube videos). For instance, what should happen if the chara ...

Who needs a proper naming convention when things are working just fine? What's the point of conventions if they don't improve functionality?

I am a newcomer to the world of JavaScript programming and stumbled upon this example while practicing. <html> <head> <script type="text/javascript"> function changeTabIndex() { document.getElementById('1').tabIndex="3" d ...

utilize dynamic variable within the template's views

Here is a snippet of my HTML code var marker; function initMap() { map = new google.maps.Map(document.getElementById("mymap"), myOptions); getMapMetadata([]); // setInterval(function(){ getMapMetadata([]); }, 3000); } function createMarke ...

Should front-end and back-end share Typescript data modeling through classes or interfaces?

I'm currently exploring the best approach to share the same data types between the client (React) and the server (Express + Socket.IO). Within my game, there are various rooms each storing the current status, such as: class GameRoom { players: P ...

Extract specific form data to use in a jQuery.ajax request

Having trouble extracting the current selected value from a dropdown form in AJAX URL. The Form: <form name="sortby"> <select name="order_by" onchange="myFunction()"> <option<?php if(isset($_GET['order_by']) && ...

Please upload the image by clicking the "Upload Files!" button instead of relying on the input change

I am looking to enhance my image uploading process by allowing users to upload multiple images after clicking the Upload Files! button, rather than relying on the input change event. Below is the jQuery code I am using (which I found here): index.html &l ...

Issue with calling function from props in React is not being resolved

There seems to be an issue with the function not being called when passed into a functional component. While the onSubmit function is triggered, the login(email, password) function inside the Login component is never executed. Despite placing console.log s ...

What is the best way to align a TabPanel component at the center using React Material UI

As I attempt to compile a list of articles while switching to a list of other entities in React + material UI, I have encountered some difficulties. Specifically, I am struggling to center the Card displaying an article in alignment with the centered Tabs. ...

When viewing a webpage on a small browser, the content will automatically expand to fill the

Attempting to utilize responsive CSS media queries to hide the sidebar unless the screen is large or a tablet big enough in landscape mode. It appears to be functioning properly while resizing the browser, but at a certain size, it occupies the entire scre ...

Stop modal from closing in the presence of an error

My approach involves using a generic method where, upon adding a food item, a modal window with a form opens for the user to input their details. However, since backend validation for duplicate items can only be retrieved after the API call completes. I w ...

combine object with an array attribute

If we have the following objects: let firstObject = {items: ["apple"]}; let secondObject = {items: ["orange"]}; and then execute Object.assign(firstObject, secondObject); the new state will be: firstObject.items[0] //"orange" firstObject.items === sec ...

How can I trigger a row click event while a TextInput is in focus? (react-native)

Whenever I tap on a ListView item, the TouchableOpacity functions properly. However, when a TextInput is in focus, it requires two taps for it to work - the first tap only removes the focus from the TextInput. Is there a way to make it work without havin ...

Why does Res.send return an empty object when console.log indicates it is not empty?

I am currently facing a challenge while using the Google Sheets API with Express, as I have limited experience with JavaScript. My goal is to pass a JSON object from Express to React, but for some reason, when I send the object, it appears empty on the fro ...

Vue component not receiving the updated prop value from parent component

I am encountering a problem with my parent-child component setup. The issue arises when I pass a validation field as a prop from the parent to the child, but it doesn't update upon the first click of the submit button in the child component. To explai ...

Unexpected Error: The axiosCookieJarSupport function is throwing a TypeError, functioning properly in Node.JS but not in .vue pages. What could

Struggling with a function that authenticates on a website, it runs smoothly in a basic node.js script but fails when executed from a .vue page within the NuxtJS framework. The error message received when running in the .vue page is TypeError: axiosCookie ...

"Ensuring a DIV element has a height of 100% within

Is there a way to set and enforce a div's height to be 100% of the browser window, another div, or a table cell without resorting to complicated hacks found on Stack Overflow or other websites? ...