In the realm of HTML Canvas, polygons intricately intertwine with one another

Currently, I am attempting to create multiple polygons from a large JSON file. Instead of being separate, the polygons seem to be connected in some way.

The project is being developed in next.js.

Below are the relevant code snippets:

Canvas.tsx

// ../components/Canvas.tsx

import React, { useRef, useEffect } from 'react'

const Canvas = props => {
  
  const canvasRef = useRef(null)
  
  useEffect(() => {
    const canvas: any = canvasRef.current
    const context = canvas.getContext('2d')

    context.fillStyle = '#FF0000'
    context.beginPath()
    { props.x.map((pointx, i) => context.lineTo(0.25 * pointx, 0.25 * props.y[i])) } // Scaled down to 25% of original size
    context.closePath()
    context.fill()
  }, [])
  
  return <canvas ref={canvasRef} {...props} width={props.width} height={props.height} style={{ zIndex: 20, position: 'absolute', objectFit: 'contain' }}/>
}

export default Canvas

index.tsx

import React, { ReactElement, useEffect, useRef, useState } from 'react'
import Image from 'next/image'
import dynamic from "next/dynamic";
import data from '../public/11_regions-copy.json'
import Canvas from '../components/Canvas';


export const getServerSideProps = async () => {

  let xTemp: any[] = []
  let yTemp: any[] = []

  for (var i = 0; i < Object.keys(data).length; i++) {
    xTemp.push(data[i].all_points_x)
    yTemp.push(data[i].all_points_y)
  }
  for (var j = 0; j < Object.keys(data).length; j++) {
    let xArray = xTemp[j]
    xArray.push(xArray[0])

    let yArray = yTemp[j]
    yArray.push(yArray[0])
  }
  
  let x = [].concat.apply([], xTemp);
  let y = [].concat.apply([], yTemp);


  return {
    props: {
      x,
      y
    },
  }
}

function Home({ x, y }: any): ReactElement {

  return (
    <div>
      <Canvas width={1680} height={756} x={x} y={y} />
    </div>
  )
}

export default Home

JSON file used: json

If you have any insights or suggestions, please feel free to share them!

Answer №1

The issue arises when you merge all regions from your data source into a single extended path. This occurs within the getServerSideProps function (which can be a bit clumsy by the way).

Therefore, your data structure appears as follows:

{
    "0": {

        "all_points_x": [ ... ],
        "all_points_y": [ ... ]
    },
    "1": {
        "all_points_x": [ ... ],
        "all_points_y": [ ... ]
    },
    // ...
}

Your getServerSideProps transforms it into this format:

{
    props: {
        x: [ ... ],
        y: [ ... ],
    }
}

This results in drawing a single long path as shown here:

context.beginPath()
{ props.x.map((pointx, i) => context.lineTo(0.25 * pointx, 0.25 * props.y[i])) }
context.closePath()
context.fill()

To achieve the desired outcome, instead of merging all regions into one path, draw each region as a separate path using the following approach:

// For instance, `data` could be fetched like:
// const data = await (await fetch('11_regions-copy.json')).json();

Object.values(data).forEach(({all_points_x: x, all_points_y: y}) => {
  ctx.beginPath();

  x.forEach((x, i) => {
    ctx.lineTo(0.25 * x, 0.25 * y[i]);
  });

  ctx.closePath();
  ctx.fill();
});


In response to Kaiido's suggestion, you could consider drawing a single path by utilizing the moveTo method.

ctx.beginPath();

Object.values(data).forEach(({all_points_x: x, all_points_y: y}) => {
  ctx.moveTo(0.25 * x[0], 0.25 * y[0]);

  x.forEach((x, i) => {
    ctx.lineTo(0.25 * x, 0.25 * y[i]);
  });
});

ctx.closePath();
ctx.fill();

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

Trouble with meta og:image on my SSL-secured WordPress site

Having some trouble adding meta properties to my WordPress website that is SSL certified. When I share the link on Skype and WhatsApp, the og:image is not working. I've tried multiple plugins and even directly added HTML code to my WordPress theme hea ...

Creating a textfield in Material UI that adjusts its size according to the length of the placeholder text

import * as React from "react"; import Container from "@mui/material/Container"; import Input from "@mui/material/Input"; export default function CustomInputField() { setTimeout(() => { let element = document.getElem ...

Is there a way to adjust a 5-minute countdown interval timer by 1 minute in a react JS application?

I am in need of creating a 5-minute interval timer using react JS, with a 1-minute offset. The current timer I have functions like this: 1:00 => 1:05 => 1:10 => 1:15 => 1:20. However, I require it to be adjusted to display: 1:01 => 1:0 ...

"Utilizing an ellipsis within a span element in a table cell to achieve maximum cell

Update Note: Primarily targeting Chrome (and maybe Firefox) for an extension. However, open to suggestions for a universal solution. Additional Information Note: Discovered that lack of spaces in text for A causing overflow issues with B. Situation seem ...

Learn how to efficiently apply styles to multiple objects within an array using the material-ui library

Currently, I'm utilizing the functional component of React.js. Within this component, I have an array of objects that contain specific styles. const data = [ { id: 1, color: '#000' }, { ...

How can we align the top edge of a div to the center of a circle within a separate div in a responsive manner?

I want to create 2 stacked divs: the first div contains a circular image, and the second div contains text. I want the second div to always cover half of the circle, with its upper edge positioned at the center point of the circle. This is my code: .cov ...

Converting non www to www in React.js

I want to redirect users from http://example.com to http://www.example.com. If I'm using nginx + php, I can achieve this with the following configuration: server { listen 80; server_name example.com; return 301 http://www.example.com$req ...

XML remains unchanged

Recently delving into the world of node.js and reactjs, I am faced with the challenge of transpiling my index.js file which serves as the entry point for my small application. Utilizing webpack, I have provided the package.json configuration below: src/i ...

Separate compound words without hyphens at the boundaries of each word

I am currently incorporating the use of Bootstrap for my project. Let's assume that I have text displayed in this way: "Stackoverflow" Is there a method to automatically ensure that it breaks like below if the text exceeds the container: "Stack ...

The functionality of CSS scroll snap does not seem to be compatible with the CSS Grid

When utilizing CSS scroll snap with Flexbox, the snapping functionality works adequately: * { box-sizing: border-box; margin: 0; padding: 0; } .slider { font-family: sans-serif; scroll-snap-type: mandatory; scroll-snap-points-y: repeat(100vw ...

Implementing momentLocalizer with moment.js in react-big-calendar alongside fullcalendar.js

I'm currently working with react-big-calendar and I require assistance in setting up localization as per the example provided on GitHub. import BigCalendar from 'react-big-calendar'; import moment from 'moment'; BigCalendar.setLo ...

"The TextInput component in ReactNative is preventing me from inputting any text

Experiencing issues with the iOS and Android simulators. Upon typing, the text disappears or flickers. I attempted initializing the state of the texts with preset values instead of leaving them empty. However, this caused the TextInput to stick to the ini ...

Encountering an error stating "Argument of type 'X' is not assignable to parameter of type 'X' in the NextApiResponse within NextJS."

Here is the code snippet I am working with: type Data = { id: string; name: string; description: string; price: number; }; const FetchMeals = async (req: NextApiRequest, res: NextApiResponse<Data>) => { const response = await fetch( ...

"Enjoy a unique browsing experience with a two-panel layout featuring a fixed right panel that appears after scrolling

I am facing difficulty in designing a layout with two panels where the left panel has relative positioning and the right panel becomes fixed only after a specific scroll point. Additionally, I need the height of the right panel to adjust when the page scro ...

When utilizing Next.js with TypeScript, you may encounter an error message stating that the property 'className' is not found on the type 'IntrinsicAttributes & IntrinsicClassAttributes'

I recently put together a basic nextjs app using typescript. Here's the link to the example: https://github.com/zeit/next.js/tree/master/examples/with-typescript However, I encountered an issue where I am unable to add the className attribute to any ...

Struggling with a pesky API bug in my React project, can't seem to crack it

I currently have an API call set up with two different search buttons tied to a single input box. Each button modifies the API call using state, as shown in the code snippet below. Both buttons work correctly when used independently. However, I'm fac ...

How to keep an image anchored at the bottom of the page without overlapping other content

I'm trying to have a logo image stay fixed at the bottom of a navigation drawer, but when I use absolute positioning and set it to the bottom, it overlaps with the list items on shorter devices. When the scroll bar appears due to shrinking the browser ...

Automatically focus on Material UI Checkbox when typing in input field using ReactJS

Looking for some assistance with a coding issue. I've been working on a project using the demo for Tags with multiple checkboxes found in the documentation. You can view my code sandbox version at this link. All I've done is added an input field, ...

Creating personalized styles for my React components with the help of styled-components

Exploring the power of styled-components for custom styling on child components has been an interesting journey for me. For instance, I recently crafted a unique card component named myCard. Take a look at how it's structured: import React from "rea ...

Unable to render images in React due to a technical issue

I'm having trouble with my React Slick slider - the images are not displaying correctly when I map them. Some people have suggested using the Require() statement, but when I tried it, I ended up with a blank page. This is how I've set up my com ...