admin管理员组

文章数量:1400167

I want to be able to draw svg with dynamic value (color) to the canvas. I'd tried making the svg react ponent, so I could pass the color to the svg, but I'm then confused how to draw the react svg ponent to the canvas.

P.S. Best would be if the svg would be stored in seperate file.

Working static svg example:

import ant_skin_url from '../../assets/AntSkin.svg';

const ant_skin = new Image();
ant_skin.src = ant_skin_url;

context.drawImage(
  ant_skin,
  i * width_cell,
  ii * height_cell,
  width_cell,
  height_cell,
);

React svg ponent, but confused how to handle the output (draw this in the canvas):

export const AntSkin = (color) => 
  <svg>
    ...
  </svg>

I want to be able to draw svg with dynamic value (color) to the canvas. I'd tried making the svg react ponent, so I could pass the color to the svg, but I'm then confused how to draw the react svg ponent to the canvas.

P.S. Best would be if the svg would be stored in seperate file.

Working static svg example:

import ant_skin_url from '../../assets/AntSkin.svg';

const ant_skin = new Image();
ant_skin.src = ant_skin_url;

context.drawImage(
  ant_skin,
  i * width_cell,
  ii * height_cell,
  width_cell,
  height_cell,
);

React svg ponent, but confused how to handle the output (draw this in the canvas):

export const AntSkin = (color) => 
  <svg>
    ...
  </svg>
Share Improve this question asked Apr 26, 2022 at 9:08 Jakub HamplJakub Hampl 2393 silver badges17 bronze badges 5
  • Is it have to rendered inside a canvas? If so, I don't think there is a point of importing from the svg file. Instead, bine the svg content with the variable (e.g. '<svg><path d="..." fill="' + color + '" /></svg> ) and render it inside a canvas – Mosh Feu Commented Apr 26, 2022 at 12:17
  • I just wanted to make it seperated, but it doesn't have to be that way. With the method you're suggesting, how would I render this svg into the canvas? @MoshFeu – Jakub Hampl Commented Apr 26, 2022 at 12:27
  • To be more specific, how can I draw to the canvas from this object, which I got by console logging the variable with svg element. i.imgur./vx9MlPh.png – Jakub Hampl Commented Apr 26, 2022 at 12:47
  • 1 This is what I mean - codesandbox.io/s/distracted-wiles-lj6wbg?file=/src/Icon.js – Mosh Feu Commented Apr 26, 2022 at 13:49
  • This works great! Thank you so much, you can send your snippet as the answer and I will accept it. – Jakub Hampl Commented Apr 26, 2022 at 14:30
Add a ment  | 

1 Answer 1

Reset to default 6

Since you don't want to render the svg but take it into a canvas, importing from .svg won't be much helpful.

You can create a ponent that:

  1. Receives a color as prop
  2. Has the svg content as string

On mount, it bines the svg string and the color, converts it to base64 (this is what webpack does when importing from .svg) and feed the canvas the same way you do.

This is how it looks

import { useEffect, useMemo, useRef } from "react";

export const Icon = ({ color }) => {
  const ref = useRef();
  const svg = useMemo(
    () => `<svg xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" height="100px" width="100px">
    <g>
      <path color="${color}" d="M28.1,36.6c4.6,1.9,12.2,1.6,20.9,1.1c8.9-0.4,19-0.9,28.9,0.9c6.3,1.2,11.9,3.1,16.8,6c-1.5-12.2-7.9-23.7-18.6-31.3   c-4.9-0.2-9.9,0.3-14.8,1.4C47.8,17.9,36.2,25.6,28.1,36.6z"/>
      <path color="${color}" d="M70.3,9.8C57.5,3.4,42.8,3.6,30.5,9.5c-3,6-8.4,19.6-5.3,24.9c8.6-11.7,20.9-19.8,35.2-23.1C63.7,10.5,67,10,70.3,9.8z"/>
      <path color="${color}" d="M16.5,51.3c0.6-1.7,1.2-3.4,2-5.1c-3.8-3.4-7.5-7-11-10.8c-2.1,6.1-2.8,12.5-2.3,18.7C9.6,51.1,13.4,50.2,16.5,51.3z"/>
      <path color="${color}" d="M9,31.6c3.5,3.9,7.2,7.6,11.1,11.1c0.8-1.6,1.7-3.1,2.6-4.6c0.1-0.2,0.3-0.4,0.4-0.6c-2.9-3.3-3.1-9.2-0.6-17.6   c0.8-2.7,1.8-5.3,2.7-7.4c-5.2,3.4-9.8,8-13.3,13.7C10.8,27.9,9.8,29.7,9,31.6z"/>
      <path color="${color}" d="M15.4,54.7c-2.6-1-6.1,0.7-9.7,3.4c1.2,6.6,3.9,13,8,18.5C13,69.3,13.5,61.8,15.4,54.7z"/>
      <path color="${color}" d="M39.8,57.6C54.3,66.7,70,73,86.5,76.4c0.6-0.8,1.1-1.6,1.7-2.5c4.8-7.7,7-16.3,6.8-24.8c-13.8-9.3-31.3-8.4-45.8-7.7   c-9.5,0.5-17.8,0.9-23.2-1.7c-0.1,0.1-0.2,0.3-0.3,0.4c-1,1.7-2,3.4-2.9,5.1C28.2,49.7,33.8,53.9,39.8,57.6z"/>
      <path color="${color}" d="M26.2,88.2c3.3,2,6.7,3.6,10.2,4.7c-3.5-6.2-6.3-12.6-8.8-18.5c-3.1-7.2-5.8-13.5-9-17.2c-1.9,8-2,16.4-0.3,24.7   C20.6,84.2,23.2,86.3,26.2,88.2z"/>
      <path color="${color}" d="M30.9,73c2.9,6.8,6.1,14.4,10.5,21.2c15.6,3,32-2.3,42.6-14.6C67.7,76,52.2,69.6,37.9,60.7C32,57,26.5,53,21.3,48.6   c-0.6,1.5-1.2,3-1.7,4.6C24.1,57.1,27.3,64.5,30.9,73z"/>
    </g>
    </svg>`,
    [color]
  );

  useEffect(() => {
    const image = new Image();
    const context = ref.current.getContext("2d");

    image.src = `data:image/svg+xml;base64,${window.btoa(svg)}`;
    image.onload = () => {
      context.drawImage(image, 0, 0);
    };
  }, [svg]);

  return <canvas ref={ref} width="200" height="200" />;
};

Demo

本文标签: javascriptDraw svg with dynamic value on canvasStack Overflow