Add class to vector path

Hi all. Didn´t find an appropriate solution for this: I want to fill an irregular shape with a stripe pattern by adding a class to the vector´s path. I can do something like filling the path with a color but not changing the pattern by adding a class to the path. Tried it with 'classList.add' and with 'setAttribute' (If I assign a class to the vector shape itself the bounding box is filled with the pattern...). Any idea?

Thanks in advance,
Kalle

addClassToPath.zip (43.4 KB)

Not at Mac

Does this hep

Here is one way to do this using an external SVG added to the innerHTML of an empty Hype element. There are probably other variations of this approach that would also work.

SVG_PatternSwitcher.hype.zip (105.5 KB)

Not possible if I recall correctly. SVG uses the fill method also for images and in that case they need to reference them from a def image definition. As Hype creates that def structure you could just set the image in there and add the ID in a fill=“url#imageid)” statement.

I might have an exploration of that in my experiments folder. Let me search later.

From the archives:

function setSVGImage(svgNode, imageUrl) {
	var defs = svgNode.querySelector("defs");
	var pattern = defs.querySelector("pattern");
	var patternId = pattern.getAttribute("id");
	var image = pattern.querySelector("image");
	image.setAttribute("href", imageUrl);
	
	var path = svgNode.querySelector("path");
	if (path) {
		path.setAttribute("fill", 'url(#' + patternId + ')');
	}
}

usage would be in your case

let myVector = document.querySelector ('.myVector');
setSVGImage(myVector, '${resourcesFolderName}/stripes.png')
1 Like

Hei all, thanks for your kind help. Since you all go almost into the same direction - best fit for me is Max' solution. Works pretty well, but - since I need this technique for filling countries on maps I have one problem: The pattern adjusts itself to the size of the svg element.

image

How it looks like now...

image

How it should look like

My solution for now is to make one country out of the two, but what, if the countries are not neighbours? The pattern should look always the same in dimension. Maybe - in this case - it´s better to work with masks...

Hi there! Just wanted to let you know that I, Hype ChatGTP, was involved in creating the code and writing most of the text and documentation found in this post. The creation was guided and tested by @MaxZieb.
function setSVGImage(svgNode, imageUrl) {
  var defs = svgNode.querySelector("defs");
  var pattern = defs.querySelector("pattern");
  var patternId = pattern.getAttribute("id");
  var image = pattern.querySelector("image");

  // Set the patternUnits and patternContentUnits attributes to "objectBoundingBox"
  pattern.setAttribute("patternUnits", "objectBoundingBox");
  pattern.setAttribute("patternContentUnits", "objectBoundingBox");

  // Use the bounding box of the <path> element to calculate the scaling factor
  var path = svgNode.querySelector("path");
  var bbox = path.getBBox();
  var scaleFactor = 100 / bbox.width; // <-- change 100 to the width of your image at 1:1

  // Use the calculated scaling factor to set the patternTransform attribute
  pattern.setAttribute("patternTransform", "scale(" + scaleFactor + ")");

  image.setAttribute("href", imageUrl);

  if (path) {
    path.setAttribute("fill", 'url(#' + patternId + ')');
  }
}

The code defines a function named setSVGImage that takes two arguments: an svgNode and an imageUrl . The function modifies the svgNode by adding an image to it using the imageUrl provided. The function does this by first selecting the defs element, pattern element, and image element from the svgNode . It then sets the patternUnits and patternContentUnits attributes of the pattern element to "objectBoundingBox" .

Next, the function selects a path element from the svgNode and uses it to calculate a scaling factor for the image. The scaling factor is calculated by dividing the width of the path element by 100. This scaling factor is then used to set the patternTransform attribute of the pattern element. Finally, the href attribute of the image element is set to the provided imageUrl and the path element's fill attribute is set to the pattern element. This causes the image to be added to the svgNode at the correct size and position.

The comment in the code states that the value 100 in the line var scaleFactor = 100 / bbox.width; should be replaced with the width of the image at 1:1. This is because the scaleFactor is calculated by dividing the width of the path element by the width of the image at 1:1. By default, the code uses the value 100 for this width, but this may not be the correct value if the image being used has a different width. The comment is included as a reminder for anyone using the code to replace the value 100 with the actual width of their image at 1:1. This will ensure that the image is scaled correctly when added to the svgNode .


Note from @MaxZieb : there might be a better solution using UserSpace coordiantes (hence no scale factor) … I just had that generated based on a quick request to find a solution.

3 Likes