How to draw Polyline object shaped exactly same wi

2019-07-27 21:36发布

Doughnut picture

For example, given image like above, what I want to do is draw the exact same shaped polyline object on SVG(Im creating a 'drawing' or should I say 'brush' tool based on SVG and that is why Im using polyline so that user can paint with his mouse or can even use eraser with his or hers mouse). And following is how I would achieve this.

  1. draw the given image on canvas context.
  2. get all the coordinates of pixel that is colored #000000.
  3. with that list of coordinates create a Polyline on SVG.

and by this process I get this as a result doughnut drawin with svg polyline(now this is just an example result that it is formed ugly because I had to draw it manually with my hand. But my purpose is to get same shaped with an input image)

But I'm not sure if this is the only way or even not sure if I should stick with SVG. Are there any other good ways to achieve this? or would using canvas instead of SVG make it easier?

2条回答
够拽才男人
2楼-- · 2019-07-27 22:01

This is supposing that you already have an SVG path.

In order to draw a polygon you will need to split your path by the M commands. In the next example I did it manually but you can do it dynamically. This is important because otherwise you'll get a split in the polygon.

You will also need to set a precision, meaning the distance between the points of the polygon.

Please read the comments in my code.

let paths = document.querySelectorAll("#theGroup path");
let precision = 5;//how far one of other the points of the polygon are
let points = [];// the array of points

// for each path in the array of paths 
paths.forEach(p=>{
  // get the total length
  let totalLength = p.getTotalLength();
  // get the number of points for the polygon in base of the precision
  let numPoints = ~~(totalLength / precision);
  // calculate the segment length
  let segmentLength = totalLength / numPoints;
 
  for(let i = 0; i <= numPoints; i++ ){
  let point = p.getPointAtLength(i*segmentLength);
  // get the coordinates of this point and push it
  points.push(point.x);
  points.push(point.y);
}
})

//set the value for the points attribute of the polygon
poly.setAttributeNS(null,"points", points.join())
svg{border:1px solid; width:90vh;}
path{fill:none}
<svg viewBox="0 0 531 531">
<g id="theGroup">
	<path id="donut" d="M268.64,76.066c70.065,2.632,125.154,32.347,163.73,91.372
		c14.944,22.864,23.47,48.161,27.698,75.22c3.987,25.512,2.188,50.551-3.64,75.354c-4.821,20.522-13.383,39.648-24.866,57.406
		c-2.003,3.099-3.899,3.396-7.365,1.548c-30.011-16.005-64.509-10.767-87.731,14.13c-6.295,6.748-9.985,15.893-15.108,23.783
		c-1.548,2.384-3.508,5.256-5.938,6.189c-19.202,7.375-32.874,20.547-41.279,39.064c-1.911,4.211-4.254,5.562-8.308,5.085
		c-13.198-1.554-26.507-2.515-39.562-4.873c-30.46-5.502-57.275-19.262-81.055-38.724c-28.703-23.491-49.496-52.646-61.424-88.046
		c-7.479-22.198-11.34-44.892-10.42-68.225c2.042-51.761,20.944-96.305,57.854-133.023c22.272-22.156,48.427-37.859,78.3-47.183
		C228.671,79.17,248.365,75.884,268.64,76.066z"/> 
                      
<path id="hole" d="M340.466,271.259c0.179-40.212-32.175-73.14-72.067-73.348
		c-40.072-0.208-73.264,32.326-73.485,72.032c-0.226,40.441,32.218,73.372,72.436,73.522
		C307.646,343.616,340.286,311.382,340.466,271.259z"/>
</g>
  
  <polygon id="poly" fill="gold" points = "" />
</svg>

查看更多
可以哭但决不认输i
3楼-- · 2019-07-27 22:05

This shape can be drawn with circles.
Cutouts made using a mask composed of circles

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
    width="405" height="401" viewBox="0 0 405 401" >  
<defs>
<mask id="msk1" >
	<rect width="100%" height="100%" fill="white" />
<g fill="black">
	<circle cx="202" cy="200" r="40"   />
	<circle cx="260" cy="298" r="40"   />
	<circle cx="215" cy="303" r="20"   />
</g>
</mask>
</defs>	
<circle cx="202" cy="200" r="98"  fill="black" mask="url(#msk1)" />

查看更多
登录 后发表回答