I should make the next diagram according to input data.
The main problem now is Polygon with double borders.
I tried shadows and double polygons, it doesn't work well.
Any idea?
I used next code to create points for Polygon
const p: number = includeChapter ? chapter.points : 1;
const x: number = cx + Math.round(Math.sin(i * angle) * R * p);
const y: number = cy - Math.round(Math.cos(i * angle) * R * p);
If I change radius and trying to create two different polygons i have next thing
The best way is to use a clipping path or mask. Here is a clipping path version.
<svg width="400" viewBox="-100 -100 200 200">
<defs>
<clipPath id="graph-clip">
<polygon points="0,-85, 60,-60, 85,0, 35,35, 0,85, -35,35, -85,0, -35,-35"/>
</clipPath>
</defs>
<!-- Draw the shape in light orange -->
<polygon points="0,-85, 60,-60, 85,0, 35,35, 0,85, -35,35, -85,0, -35,-35"
fill="none" stroke="rgb(255,210,128)" stroke-width="10"/>
<!-- Now draw the shape again. This time in a darker orange. But we clip the stroke
to the shape so only the inside of the stroke is visible -->
<polygon points="0,-85, 60,-60, 85,0, 35,35, 0,85, -35,35, -85,0, -35,-35"
fill="none" stroke="orange" stroke-width="10" clip-path="url(#graph-clip)"/>
</svg>
Note that all the polygon definitions are exactly the same. So you can use <use> to simplify things.
<svg width="400" viewBox="-100 -100 200 200">
<defs>
<clipPath id="graph-clip">
<polygon id="graph-shape" points="0,-85, 60,-60, 85,0, 35,35, 0,85, -35,35, -85,0, -35,-35"/>
</clipPath>
</defs>
<use xlink:href="#graph-shape"
fill="none" stroke="rgb(255,210,128)" stroke-width="10"/>
<use xlink:href="#graph-shape"
fill="none" stroke="orange" stroke-width="10" clip-path="url(#graph-clip)"/>
</svg>
Related
I'm using SVG in HTML to draw a bended word along a path. Now that I managed to do draw the text, I need to split the word in 2 colors along the path that the word sits on. You can see the effect I'm trying to make in the image. Does anyone know how can I split the word in such a way? (I'm not sure if this matters, but the word is constantly bended, stretched and moved by the user, by modifying the "d" attribute of the path.)
var path = document.getElementById("Path");
var textPath = document.getElementById("TextPath");
document.onmousemove = function(e){
path.setAttribute("d", `M 100 100 q ${e.x-100} ${e.y-100} 230 0`);
textPath.setAttribute("textLength", path.getTotalLength() + "px")
}
svg {
width: 500px;
height: 500px;
}
<svg>
<path id="Path" d="M 100 100 q 50 -100 230 0" stroke="#000000" stroke-width="1" fill="none"></path>
<text id="Text" fill="#000000" font-size="64px">
<textPath startOffset="0%" id="TextPath" alignment-baseline="middle" href="#Path" startOffset="0%" startOffset="0%">Example</textPath>
</text>
</svg>
Here's a simpler version of what I have now. What I want to happen, is to color everything above the curve with one color and everything below with another.
One way of doing it: you use the text twice: once filled with color A and once filled with color B. Next you clip the second text with the path.
<svg viewBox="0 0 260 200">
<defs>
<path id="pth" d="M70,150 C10,40 240,40 180,150" stroke="red" fill="none" />
<text id="txt" font-size="45" text-anchor="middle" dominant-baseline="central">
<textPath font-size="35" startOffset="50%" href="#pth">
SSSSSSSSSSSS
</textPath>
</text>
<clipPath id="cp">
<use href="#pth" />
</clipPath>
</defs>
<use href="#txt" fill="blue" />
<use href="#txt" fill="orange" clip-path="url(#cp)" />
</svg>
Just like this:
It has different width.
How you do this in SVG is to place one circle directly on top of the other.
<svg width="200" height="200">
<circle cx="100" cy="100" r="70" fill="none" stroke="#ccc" stroke-width="1"/>
<circle cx="100" cy="100" r="70" fill="none" stroke="#ccc" stroke-width="5"
stroke-dasharray="413.4 440" transform="rotate(-90 100 100)"/>
</svg>
The two additional attributes on the second (front) circle perform the following functions:
stroke-dasharray="413.4 440" makes a dash pattern with the effect of drawing 94% of the circle circumference (2 * PI * 70 = 440).
transform="rotate(-90 100 100)" rotates the circle 90 degrees anti-clockwise so that the "progress bar" starts at 12 o'clock. By default the dash pattern of a circle starts at 3 o'clock.
I want to move object through svg path on scroll=) I was trying to add parts of path on scroll into path, but it still doesn't work. Help!!!=)
https://jsfiddle.net/YuriiBielozertsev/Ltx9ed0L/
<?xml version="1.0"?>
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Draw the outline of the motion path in grey, along with 2 small circles at key points -->
<path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110" stroke="green" stroke-width="2" fill="none" id="theMotionPath"/>
<circle cx="10" cy="110" r="3" fill="#000"/>
<circle cx="110" cy="10" r="3" fill="#000"/>
<!-- Red circle which will be moved along the motion path. -->
<circle cx="0" cy="" r="5" fill="red">
<!-- Define the motion path animation -->
<animateMotion dur="6s" repeatCount="indefinite">
<mpath xlink:href="#theMotionPath"/>
</animateMotion>
</circle>
</svg>
Something like this?
How this works:
When we get a scroll event we:
Calculate how far down the page we are
Convert this percentage to a position on the path using the <path> element functions getTotalLength() and getPointAtLength().
Reposition the dot so that it appears at this point.
function positionTheDot() {
// What percentage down the page are we?
var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
// Get path length
var path = document.getElementById("theMotionPath");
var pathLen = path.getTotalLength();
// Get the position of a point at <scrollPercentage> along the path.
var pt = path.getPointAtLength(scrollPercentage * pathLen);
// Position the red dot at this point
var dot = document.getElementById("dot");
dot.setAttribute("transform", "translate("+ pt.x + "," + pt.y + ")");
};
// Update dot position when we get a scroll event.
window.addEventListener("scroll", positionTheDot);
// Set the initial position of the dot.
positionTheDot();
.verylong {
height: 2000px;
}
svg {
position: fixed;
width: 200px;
height: 200px;
}
<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Draw the outline of the motion path in grey, along with 2 small circles at key points -->
<path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110" stroke="green" stroke-width="2" fill="none" id="theMotionPath"/>
<circle cx="10" cy="110" r="3" fill="#000"/>
<circle cx="110" cy="10" r="3" fill="#000"/>
<!-- Red circle which will be moved along the motion path. -->
<circle cx="0" cy="0" r="5" fill="red" id="dot"/>
</svg>
<div class="verylong">
</div>
There is an imaginary square which I want to draw as two halves, i.e. two triangles. Whilst they should perfectly fit together and make a square, a tiny line caused by anti-aliasing appears.
These triangles should be of different color, but I left both them black in the given example to make the line more visible.
<svg width="100" height="100"
viewPort="0 0 100 100" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="first">
<path d="M 0 0 L 100 100 L 0 100 Z" fill="red"/>
</clipPath>
<clipPath id="second">
<path d="M 0 0 L 100 0 L 100 100 Z" fill="red"/>
</clipPath>
</defs>
<rect width="100" fill="black" height="100"
clip-path="url(#first)"/>
<rect width="100" fill="black" height="100"
clip-path="url(#second)"/>
</svg>
JSFiddle
I am open to solutions - canvas, WebGL etc. I just want to know possible solutions which would improve rendering.
I'm not sure why you are seeing the line using clip paths, but if I just change it around to using regular polygons and use shape-rendering: crispEdges the line doesn't appear:
<svg width="100" height="100" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<polygon points="0,0 100,0 100,100" style="fill:black;shape-rendering:crispEdges;" />
<polygon points="0,0 100,100 0,100" style="fill:black;shape-rendering:crispEdges;" />
</svg>
I've been messing around with SVG path animations. My SVG has 2 layers in it; a grey egg and an orange egg. The orange egg animates over the top of the grey egg, this part works fine. However, both paths technically have the same width, but when I animate the orange egg, the grey egg's path looks like it's reduced by 50%.
Below is an image and the code.
var path = document.querySelector('#egg-orange path');
var length = path.getTotalLength();
var percent = length/100;
var desiredPercent = 50;
var currentPercent = percent * (100 - desiredPercent); // 50%
// Clear any previous transition
path.style.transition = path.style.WebkitTransition =
'none';
// Set up the starting positions
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = length;
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
path.getBoundingClientRect();
// Define our transition
path.style.transition = path.style.WebkitTransition =
'stroke-dashoffset 2s ease-in-out';
// Go!
path.style.strokeDashoffset = currentPercent;
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 104.7 144.3" enable-background="new 0 0 104.7 144.3" xml:space="preserve">
<g id="egg-grey">
<path fill="#FFFFFF" stroke="#414042" stroke-width="10" stroke-miterlimit="10" d="M99.3,92.2c0,25.7-20.8,46.5-46.5,46.5
S6.3,117.8,6.3,92.2S27.2,5.7,52.8,5.7S99.3,66.5,99.3,92.2z"/>
</g>
<g id="egg-orange">
<path fill="#FFFFFF" stroke="#F15A29" stroke-width="10" stroke-miterlimit="10" d="M99.3,92.2c0,25.7-20.8,46.5-46.5,46.5
S6.3,117.8,6.3,92.2S27.2,5.7,52.8,5.7S99.3,66.5,99.3,92.2z"/>
</g>
</svg>
I found out that the issue was because of the white fill on the orange egg. All i needed to do was add fill-opacity="0" and hey presto, all sorted!
<g id="egg-orange">
<path fill="#fff" fill-opacity="0" stroke="#F15A29" stroke-width="10" stroke-miterlimit="10" d="M99.3,92.2c0,25.7-20.8,46.5-46.5,46.5
S6.3,117.8,6.3,92.2S27.2,5.7,52.8,5.7S99.3,66.5,99.3,92.2z"/>
</g>
EDIT:
As Paul mentioned below, you can just set fill to none and not need to touch opacity.
<g id="egg-orange">
<path fill="none" stroke="#F15A29" stroke-width="10" stroke-miterlimit="10" d="M99.3,92.2c0,25.7-20.8,46.5-46.5,46.5
S6.3,117.8,6.3,92.2S27.2,5.7,52.8,5.7S99.3,66.5,99.3,92.2z"/>
</g>