why custom svg cursor is vanishing after certain value of height and width is reached - javascript

I want to display a custom circular shape as cursor whose sizes are dynamic.
general logic i'm following is, if radius = some value and svg height and width is twice the radius
i.e for r="64" ---> width="128" height="128"
Problem statement
I found 128 is the threshold height and width.
if it is increased just by one i.e 129 then cursor will no longer appear.
How to increase cursor side beyond 128 i.e radius is beyond 64?
see below code example,
var one = document.getElementById('one');
one.style.cursor = `url('data:image/svg+xml;utf8,<svg fill="%23FF0000" width="128" height="128" xmlns="http://www.w3.org/2000/svg"><circle cx="50%" cy="50%" r="64" fill="yellow" /></svg>') 32 32, auto`;
var two = document.getElementById('two');
two.style.cursor = `url('data:image/svg+xml;utf8,<svg fill="%23FF0000" width="129" height="129" xmlns="http://www.w3.org/2000/svg"><circle cx="50%" cy="50%" r="64" fill="yellow" /></svg>') 32 32, auto`;
<!DOCTYPE html>
<html>
<body>
<div>
<div id="one" style="padding: 50px; background-color:green">one</div>
<div id="two" style="padding: 50px; background-color:red">two</div>
</div>
</body>
</html>

Related

SVG Element is Vertically Centred and I don't want it to be

I'm trying to recreate the old DVD logo that would bounce around the tv screen using the SVG html element.
<svg className='canvas'>
<svg ref={this.image} xmlns="http://www.w3.org/2000/svg" width="10%" viewBox="0 0 510 305" version="1.1">
<g ref={this.g} id="g1" transform="matrix(6,0,0,6,48.16071,-418.59098)">
<path id="path1" d="m 30.57323,69.90683 0,0.14991 0.14998,0.30006 0.15001,0.44999 0.14999,0.67505 0.37501,0.67497 0.22499,0.82497 0.22501,0.75005 0.29999,0.74996 0.22501,0.67505 0.14999,0.67497 0.15001,0.44998 0.6,1.57501 0.45,1.35003 0.29999,1.12496 0.375,0.90004 0.15001,0.74996 0.15,0.67505 0.075,0.37499 0.075,0.37498 0,0.29999 0.075,-0.075 0.075,-0.22499 0.15,-0.22507 0.22499,-0.37498 0.30001,-0.52498 0.52501,-0.59998 0.52498,-0.67497 0.67501,-0.90004 0.82499,-1.12495 0.97501,-1.20003 1.19999,-1.42502 0.30001,-0.29999 0.375,-0.44997 0.44999,-0.67505 0.67501,-0.67498 0.525,-0.74997 0.60001,-0.75004 0.67499,-0.74998 0.525,-0.59997 0.59999,-0.67505 0.37501,-0.37499 0.22499,-0.30006 0.075,-0.14991 17.24999,0 2.17501,0.14991 2.02499,0.22507 1.8,0.44998 1.72501,0.60005 1.49999,0.74997 1.35001,0.89997 1.12499,1.05003 0.975,1.05003 0.60002,1.19995 0.375,1.35002 0.075,1.35003 -0.22501,1.42494 -0.45,1.50001 -0.74999,1.35002 -0.97501,1.35003 -1.27499,1.19995 -1.425,1.12495 -1.57501,0.97504 -1.72499,0.89996 -1.875,0.82505 -2.02501,0.52505 -2.02498,0.44999 -2.10001,0.22498 -2.25,0.075 -11.55001,0 3.45001,-14.62502 8.175,0 -2.325,10.05005 1.8,0 1.425,-0.075 1.425,-0.15 1.425,-0.22499 1.19999,-0.37499 1.20002,-0.59997 1.12499,-0.60005 0.89999,-0.82498 0.75001,-0.82496 0.60001,-1.05004 0.44998,-1.20002 0.15001,-1.04995 -0.075,-0.97504 -0.29999,-0.89996 -0.6,-0.67505 -0.67501,-0.74998 -0.97499,-0.52497 -1.05,-0.44999 -1.20001,-0.30006 -1.34998,-0.14999 -1.57501,-0.075 -9.9,0 -18.75,21.30005 -7.425,-20.92506 0,-0.075 -0.075,-0.14999 0,-0.075 -0.15,-0.15 -0.075,0 -0.14999,0.15 0,0.075 0.075,0.075 0,0.15 0.075,0 0,0.075 0.22502,0.82504 0.14998,0.74997 0.075,0.90004 0.075,0.89996 0,0.75004 -0.075,0.74998 -0.075,0.52497 -0.45,1.50001 -0.825,1.35003 -0.975,1.35002 -1.20002,1.19988 -1.425,1.12495 -1.57501,0.97504 -1.79999,0.89996 -1.875,0.67505 -1.95001,0.67505 -2.09999,0.44999 -2.17501,0.22498 -2.09999,0.075 -11.625,0 3.525,-14.62502 8.175,0 -2.475,10.05005 1.95,0 1.425,-0.075 1.425,-0.15 1.275,-0.22499 1.35,-0.37499 1.19999,-0.59997 1.05002,-0.60005 0.89998,-0.82498 0.82501,-0.82496 0.52501,-1.05004 0.44998,-1.20002 0.15,-1.04995 -0.075,-0.97504 -0.375,-0.89996 -0.45,-0.67505 -0.74999,-0.74998 -0.9,-0.52497 -1.125,-0.44999 -1.2,-0.30006 -1.34999,-0.14999 -1.50001,-0.075 -10.12499,0 1.12499,-4.64996 31.12501,0" />
<path id="path2" d="m 30.64821,103.58183 -1.5,0 -2.69998,-0.15007 -1.12501,-0.14992 -1.125,-0.22506 -0.9,-0.15 -0.75,-0.29999 -0.6,-0.29999 -0.30001,-0.29999 -0.14999,-0.29998 0.14999,-0.29999 0.30001,-0.22506 0.6,-0.37499 0.75,-0.22499 0.9,-0.225 1.125,-0.14999 1.12501,-0.15007 1.34998,-0.0749 1.35,-0.075 1.5,-0.075 1.5,0.075 1.42501,0.075 1.27499,0.0749 1.27501,0.15008 0.975,0.14999 0.97501,0.225 0.67499,0.22498 0.6,0.37499 0.29999,0.22507 0.15001,0.29999 -0.15001,0.29998 -0.29999,0.29999 -0.6,0.29999 -0.67499,0.29999 -0.97501,0.15 -0.975,0.22506 -1.27501,0.14992 -1.27499,0.0751 -1.42501,0.075 -1.5,0 z m 1.5,-7.65007 -3.67499,0 -3.6,0.0751 -3.375,0.15 -3.3,0.14992 -3.225,0.15007 -3.00001,0.29999 -2.925,0.22499 -2.7,0.29998 -2.475,0.30007 -2.325,0.37498 -2.09999,0.44993 -1.875,0.37497 -1.65001,0.375 -1.275,0.52498 -1.05,0.45005 -0.825,0.44999 -0.44999,0.52498 -0.15001,0.52505 0.15001,0.44998 0.44999,0.59998 0.825,0.44999 1.05,0.45005 1.275,0.52497 1.65001,0.37499 1.875,0.37499 2.09999,0.44998 2.325,0.37498 2.475,0.30006 2.7,0.29999 2.925,0.225 3.00001,0.29999 3.225,0.15006 3.3,0.15 3.375,0.14999 3.6,0 3.67499,0.075 3.67502,-0.075 3.52499,0 3.375,-0.14999 3.29999,-0.15 3.22501,-0.15006 2.99999,-0.29999 2.92501,-0.225 2.69999,-0.29999 2.55001,-0.30006 2.25,-0.37498 2.17499,-0.44998 1.8,-0.37499 1.65001,-0.37499 1.34999,-0.52497 0.975,-0.45005 0.82502,-0.44999 0.44998,-0.59998 0.15001,-0.44998 -0.15001,-0.52505 -0.44998,-0.52498 -0.82502,-0.44999 -0.975,-0.45005 -1.34999,-0.52498 -1.65001,-0.37499 -1.8,-0.37498 -2.17499,-0.44998 -2.25,-0.37499 -2.55001,-0.30006 -2.69999,-0.29999 -2.92501,-0.22499 -2.99999,-0.29999 -3.22501,-0.15007 -3.29999,-0.14991 -3.375,-0.15 -3.52499,-0.0751 -3.67502,0" />
<path id="path3" d="m 71.59822,106.0568 -0.97501,0 -0.37499,2.92504 -0.45,0 0.375,-2.92504 -1.05001,0 0.075,-0.37506 2.475,0 -0.075,0.37506" />
<path id="path4" d="m 75.04822,108.98184 -0.45,0 0,-2.55005 -1.35001,2.55005 -0.52499,-2.55005 -0.89999,2.55005 -0.375,0 1.12499,-3.3001 0.29999,0 0.525,2.17506 1.20001,-2.17506 0.45,0 0,3.3001" />
<path id="path5" d="m 5.07322,117.53179 2.69999,-5.475 2.55001,0 -4.65,8.40004 -1.425,0 -4.57501,-8.40004 2.475,0 2.92501,5.475" />
<path id="path6" d="m 16.02321,120.45683 2.25,0 0,-8.4 -2.25,0 0,8.4 z" />
<path id="path7" d="m 28.39821,120.45683 -3.44998,0 0,-8.40004 3.44998,0 1.20001,0.075 1.12499,0.22499 1.05001,0.44998 0.82499,0.45005 0.67501,0.67498 0.525,0.67505 0.3,0.82496 0.075,0.82498 -0.075,0.90003 -0.3,0.74997 -0.525,0.75005 -0.75001,0.52497 -0.74999,0.59998 -1.05001,0.37506 -1.12499,0.22499 -1.20001,0.075 z m -0.67499,-6.97503 1.12499,0 0.9,0.225 0.67501,0.29999 0.59999,0.37499 0.45001,0.52505 0.225,0.59997 0.075,0.74998 -0.075,0.60005 -0.15001,0.52497 -0.22499,0.44999 -0.525,0.45005 -0.52501,0.29999 -0.67499,0.22491 -0.82501,0.15007 -1.04999,0.075 -0.37501,0 0,-5.55001 0.37501,0" />
<path id="path8" d="m 42.72322,113.4818 0,1.875 3.675,0 0,1.42503 -3.675,0 0,2.24998 3.89999,0 0,1.42502 -6.225,0 0,-8.40004 6.225,0 0,1.42501 -3.89999,0" />
<path id="path9" d="m 58.47322,120.45683 1.35,-0.075 1.125,-0.22499 1.04999,-0.37506 0.82501,-0.59998 0.75,-0.59997 0.525,-0.75004 0.29999,-0.74998 0.075,-0.82503 -0.075,-0.82498 -0.29999,-0.82496 -0.525,-0.60005 -0.75,-0.67498 -0.82501,-0.52505 -1.04999,-0.44998 -1.125,-0.22499 -1.35,-0.075 -1.20001,0.075 -1.12499,0.22499 -1.05001,0.44998 -0.82499,0.52505 -0.75001,0.67498 -0.52499,0.60005 -0.29999,0.82496 -0.075,0.82498 0.075,0.82503 0.29999,0.74998 0.52499,0.75004 0.75001,0.59997 0.82499,0.59998 1.05001,0.37506 1.12499,0.22499 1.20001,0.075 z m 0,-6.90003 0.89999,0.075 0.75,0.29999 0.67501,0.29999 0.525,0.37506 0.45,0.4499 0.22499,0.60005 0.075,0.52499 -0.075,0.60005 -0.22499,0.44997 -0.45,0.52499 -0.525,0.52505 -0.75,0.29999 -0.67501,0.22491 -0.89999,0.0751 -0.75,-0.0751 -0.82501,-0.22491 -0.59999,-0.29999 -0.525,-0.52505 -0.45,-0.52499 -0.22501,-0.44997 -0.075,-0.60005 0.075,-0.52499 0.22501,-0.60005 0.45,-0.4499 0.525,-0.37506 0.59999,-0.29999 0.82501,-0.29999 0.75,-0.075" />
</g>
</svg>
</svg>
This is what I've got so far. I have a parent SVG element which has some CSS styling to set its position to absolute and its width and height to 100%, so that it fills the whole window.
I then have the internal SVG element, which I've given a viewbox so that I can have the image be dynamically sized according to the size of the window.
This works but the SVG image ends up vertically centred in the window when x and y are set to 0, which is frustrating. I want the x=0 y=0 coordinate to be the top left of the window. If I am to remove the parent SVG element then the image successfully displays in the top left but I then can't use the coordinates to move it around the page, and if I don't specify a viewBox then I can use the coordinates and the origin is at the top left of the window but I have no control over the size of the image and it is rather larger than I would like.
What do I do?
Instead of using x and y to move your SVG around, you could use a translation. That would allow you to get rid of the outer SVG-element and have the inner one start positioned at the top left.
For example the CSS-rule svg { transform: translate(10px, 10px); } would move it 10px to the right and 10px down. Just set this as you would x and y otherwise.

svg cannot show tooltip normally in IE but normal Chrome

I cannot show the tooltip normally in IE but normally in Chrome.
Used some js codes to create dynamical label called title.
Add it into the svg.
Everything is right in Chrome with tooltip, but not in IE.
<svg id="lang-picker-toggler" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M217.982 201.586h-64.499c-5.537 0-10.026 4.489-10.026 10.026s4.489 10.026 10.026 10.026h53.547c-4.72 25.263-26.935 44.446-53.547 44.446-30.037 0-54.473-24.436-54.473-54.473s24.436-54.473 54.473-54.473c14.55 0 28.229 5.667 38.518 15.955 3.916 3.916 10.264 3.916 14.178 0 3.916-3.916 3.916-10.264 0-14.178-14.077-14.077-32.791-21.829-52.697-21.829-41.094 0-74.525 33.431-74.525 74.525 0 41.094 33.431 74.525 74.525 74.525s74.525-33.431 74.525-74.525c.001-5.536-4.488-10.025-10.025-10.025z"/>
<path d="M470.331 92.24H269.728l-26.935-81.355a10.025 10.025 0 00-9.518-6.875H41.669C18.693 4.01 0 22.703 0 45.679v332.412c0 22.976 18.693 41.669 41.669 41.669h203.145l27.073 81.369a10.026 10.026 0 009.513 6.861h188.932c22.976 0 41.669-18.693 41.669-41.669V133.909c-.001-22.976-18.694-41.669-41.67-41.669zM41.669 399.708c-11.919 0-21.616-9.697-21.616-21.616V45.679c0-11.919 9.697-21.616 21.616-21.616h184.364l70.691 213.516a.366.366 0 00.015.043l53.664 162.086H41.669zm295.78-116.433c.805 1.11 10.824 14.877 26.355 34.066-4.377 5.756-9.015 11.474-13.91 17.036l-29.712-89.74h87.441c-6.196 13.031-16.938 33.813-31.692 55.736-13.553-16.921-22.069-28.622-22.249-28.87-3.251-4.482-9.519-5.481-14.002-2.23-4.482 3.25-5.48 9.518-2.231 14.002zM265.946 419.76h75.162l-55.503 59.084-19.659-59.084zm226.002 46.561c0 11.919-9.697 21.616-21.616 21.616H304.575l67.015-71.339-.004-.003c.293-.312.571-.64.823-.991a10.025 10.025 0 001.39-9.022l-16.688-50.402c7.073-7.406 13.68-15.143 19.805-22.965 13.299 15.772 29.037 33.446 45.778 50.187 1.957 1.957 4.524 2.937 7.089 2.937s5.132-.979 7.089-2.937c3.916-3.916 3.916-10.264 0-14.178-17.461-17.461-34.013-36.244-47.687-52.632 21.251-30.503 35.033-59.504 40.535-71.954h21.454c5.537 0 10.026-4.489 10.026-10.026s-4.489-10.026-10.026-10.026h-66.173v-18.047c0-5.537-4.489-10.026-10.026-10.026s-10.026 4.489-10.026 10.026v18.046h-51.406l-37.178-112.292H470.33c11.919 0 21.616 9.697 21.616 21.616v332.412z"/>
</svg>
Here is my javascript:
// Create dynamically label for tooltip
var titleEle = document.createElementNS('http://www.w3.org/2000/svg', 'title');
var textString = document.createTextNode(currentLangElement.getAttribute('data-language'));
titleEle.appendChild(textString);
langPickerTogglerElement.appendChild(titleEle);
IE will not show any tooltip for the <title> element of the root <svg> element.
svg {border: 1px solid}
<svg>
<title>IE won't show this as a tooltip</title>
<rect x="50" y="50" width="50" height="50">
<title>However this will be in a tooltip even in IE</title>
</rect>
</svg>
fiddle for IE
Specs explicitly allow such behavior:
For reasons of accessibility, user agents should always make the content of the ‘title’ child element to the root svg element available to users. However, this is typically done through other means than the tooltips used for nested SVG and graphics elements, e.g., by displaying in a browser tab.
If you wish the tooltip to appear in this browser you must set the <title> of an inner element.
In your case, it could have been a <g> that would contain both <path> elements, if it wasn't for an other IE oddity where they show the tooltip only when you hover over painted areas (strokes and fills).
So given your paths don't cover the whole svg element, it's kinda risky to hope for your users will hover at the correct place.
So this leaves us with a last solution, which is to append a <rect> which will act as an invisible background covering the whole viewPort and will handle the <title>.
// We are now targetting the <rect> element
var langPickerTogglerElement = document.querySelector('#lang-picker-toggler > rect');
var currentLangElement = document.querySelector('[data-language]');
var titleEle = document.createElementNS('http://www.w3.org/2000/svg', 'title');
var textString = document.createTextNode(currentLangElement.getAttribute('data-language'));
titleEle.appendChild(textString);
langPickerTogglerElement.appendChild(titleEle);
svg {border: 1px solid}
<span data-language="My title text is awesome"></span>
<svg id="lang-picker-toggler" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="128" height="128">
<!-- our tooltip handler, must be a graphic element for IE -->
<!-- first element so it's set at the background -->
<!-- cover the whole viewPort -->
<!-- fill="none" for less work at rendering -->
<!-- pointer-events=fill so the browser can catch mouse over -->
<rect
x="0" y="0" width="512" height="512"
fill="none"
pointer-events="fill"/>
<path d="M217.982 201.586h-64.499c-5.537 0-10.026 4.489-10.026 10.026s4.489 10.026 10.026 10.026h53.547c-4.72 25.263-26.935 44.446-53.547 44.446-30.037 0-54.473-24.436-54.473-54.473s24.436-54.473 54.473-54.473c14.55 0 28.229 5.667 38.518 15.955 3.916 3.916 10.264 3.916 14.178 0 3.916-3.916 3.916-10.264 0-14.178-14.077-14.077-32.791-21.829-52.697-21.829-41.094 0-74.525 33.431-74.525 74.525 0 41.094 33.431 74.525 74.525 74.525s74.525-33.431 74.525-74.525c.001-5.536-4.488-10.025-10.025-10.025z"/>
<path d="M470.331 92.24H269.728l-26.935-81.355a10.025 10.025 0 00-9.518-6.875H41.669C18.693 4.01 0 22.703 0 45.679v332.412c0 22.976 18.693 41.669 41.669 41.669h203.145l27.073 81.369a10.026 10.026 0 009.513 6.861h188.932c22.976 0 41.669-18.693 41.669-41.669V133.909c-.001-22.976-18.694-41.669-41.67-41.669zM41.669 399.708c-11.919 0-21.616-9.697-21.616-21.616V45.679c0-11.919 9.697-21.616 21.616-21.616h184.364l70.691 213.516a.366.366 0 00.015.043l53.664 162.086H41.669zm295.78-116.433c.805 1.11 10.824 14.877 26.355 34.066-4.377 5.756-9.015 11.474-13.91 17.036l-29.712-89.74h87.441c-6.196 13.031-16.938 33.813-31.692 55.736-13.553-16.921-22.069-28.622-22.249-28.87-3.251-4.482-9.519-5.481-14.002-2.23-4.482 3.25-5.48 9.518-2.231 14.002zM265.946 419.76h75.162l-55.503 59.084-19.659-59.084zm226.002 46.561c0 11.919-9.697 21.616-21.616 21.616H304.575l67.015-71.339-.004-.003c.293-.312.571-.64.823-.991a10.025 10.025 0 001.39-9.022l-16.688-50.402c7.073-7.406 13.68-15.143 19.805-22.965 13.299 15.772 29.037 33.446 45.778 50.187 1.957 1.957 4.524 2.937 7.089 2.937s5.132-.979 7.089-2.937c3.916-3.916 3.916-10.264 0-14.178-17.461-17.461-34.013-36.244-47.687-52.632 21.251-30.503 35.033-59.504 40.535-71.954h21.454c5.537 0 10.026-4.489 10.026-10.026s-4.489-10.026-10.026-10.026h-66.173v-18.047c0-5.537-4.489-10.026-10.026-10.026s-10.026 4.489-10.026 10.026v18.046h-51.406l-37.178-112.292H470.33c11.919 0 21.616 9.697 21.616 21.616v332.412z"/>
</svg>
fiddle for IE
There's a simpler way. You can can just replace this:
var textString = document.createTextNode(currentLangElement.getAttribute('data-language'));
titleEle.appendChild(textString);
with this:
titleEle.textContent = currentLangElement.getAttribute('data-language');
which does work in IE.

HTML and SVG how to move only one endpoint of a line with mouse click?

I've been trying to figure out a way to move just one end of a line, but it keep changing the container and thus redrawing the entire line and moving it.
Here's a js fiddle: https://jsfiddle.net/h2nwygu8/1/
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Review Race</title>
</head>
<body>
<div class="wrapper">
<section>
<h1>Line Test</h1>
<div id="canvas" style="width: 960px; height:410px; border: 4px solid lime;">
<svg id="svgContainer" xmlns="http://www.w3.org/2000/svg" version="1.1" style="position: absolute; top:95px; width:960px; height:410px;">
<line id="start_line" x1="10" y1="0" x2="10" y2="960" style="stroke:rgb(255,0,0);stroke-width:3;" />
</svg>
</div>
</section>
</div>
</body>
</html>
and javascript:
function placeLine(e) {
var d = document.getElementById('start_line');
posY = e.clientY;
posX = e.clientX;
d.setAttribute("y1", posY)
d.setAttribute("x1", posX)
}
document.addEventListener("click", placeLine);
what I would like to do is have the top of the red line move around over the green box to the mouse x,y position. The bottom of the line should not move. However with each click the containers are changing and moving the entire line. You can also see there are a few issues with the offsets with the mouse x,y and the line. The only restriction is that the line needs to be able to layer over the top of the container with the green boundary.
What's the best way to do this? Thanks.
You've mixed up the height and width with regards to the x2 and y2 properties. It should start working more like you expect if you change y2 to be equal to your height (410px).
See: https://jsfiddle.net/zukrtpyg/.
HTML:
<div id="canvas" style="width: 960px; height:410px; border: 4px solid lime;">
<svg id="svgContainer" xmlns="http://www.w3.org/2000/svg" version="1.1" style="width:960px; height:410px;">
<line id="start_line" x1="0" y1="0" x2="0" y2="410" style="stroke:rgb(255,0,0);stroke-width:3;" />
</svg>
</div>
Javascript:
function placeLine(e) {
var d = document.getElementById('start_line');
posY = e.offsetY;
posX = e.offsetX;
d.setAttribute("y1", posY)
d.setAttribute("x1", posX)
}
document.getElementById('canvas').addEventListener("click", placeLine);
I've also removed the top and position declarations on the canvas element, these were causing the line to extend past the green border on the bottom.
Lastly, I've changed the click listener to be on the canvas element, that way you can use the events' offsetX and offsetY to position the line in relation to the canvas element, which is what the path coordinates are mapped to in the first place.
Using the clientX and clientY positions tries to place it in relation to the page, which doesn't map up with the position you want it to be on the canvas.
You can actually still use the clientX and clientY positions, you just have to compensate with the x and y position of the canvas element in relation to the page. You can find these out using Element.getBoundingClientRect(). See https://jsfiddle.net/th0aLcx0/ for an example.

Partially fill a shape's border with colour

I am trying to create a progress effect whereby colour fills a DOM object's border (or possibly background). The image attached should give you a better idea of what I'm going for. I have achieved the current result by adding an object with a solid background colour over the grey lines and setting its height. This object has mix-blend-mode: color-burn; applied to it which is why it only colours the grey lines underneath it.
This works okay, but ruins the anti aliasing around the circle, and also the produced colour is unpredictable (changes depending on the colour of the lines).
I feel there must be a better way of achieving this, perhaps with the canvas element. Could someone point me in the right direction please?
Thanks in advance!
This should be possible to do with Canvas and may even be possible with CSS itself by playing with multiple elements etc but I would definitely recommend you to use SVG. SVG offers a lot of benefits in terms of how easy it is to code, maintain and also produce responsive outputs (unlike Canvas which tends to become pixelated when scaled).
The following are the components:
A rect element which is the same size as the parent svg and has a linear-gradient fill. The gradient has two colors - one is the base (light gray) and the other is the progress (cyan-ish).
A mask which is applied on the rect element. The mask has a path which is nothing but the line and the circle. When the mask is applied to the rect, only this path would show through the actual background (or fill) of the rect, the rest of the area would be masked out by the other rect which is added inside the mask.
The mask also has a text element to show the progress value.
The linear-gradient has the stop offset set in such a way that it is equal to the progress. By changing the offset, we can always make sure that the path shows the progress fill only for the required length and the base (light gray) for the rest.
window.onload = function() {
var progress = document.querySelector('#progress'),
base = document.querySelector('#base'),
prgText = document.querySelector('#prg-text'),
prgInput = document.querySelector('#prg-input');
prgInput.addEventListener('change', function() {
prgText.textContent = this.value + '%';
progress.setAttribute('offset', this.value + '%');
base.setAttribute('offset', this.value + '%');
});
}
svg {
width: 200px;
height: 300px;
}
path {
stroke-width: 4;
}
#rect {
fill: url(#grad);
mask: url(#path);
}
/* just for demo */
.controls {
position: absolute;
top: 0;
right: 0;
height: 100px;
line-height: 100px;
border: 1px solid;
}
.controls * {
vertical-align: middle;
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 200 300' id='shape-container'>
<linearGradient id='grad' gradientTransform='rotate(90 0 0)'>
<stop offset='50%' stop-color='rgb(0,218,235)' id='progress' />
<stop offset='50%' stop-color='rgb(238,238,238)' id='base' />
</linearGradient>
<mask id='path' maskUnits='userSpaceOnUse' x='0' y='0' width='200' height='300'>
<rect x='0' y='0' width='200' height='300' fill='black' />
<path d='M100,0 100,100 A50,50 0 0,0 100,200 L100,300 M100,200 A50,50 0 1,0 100,100' stroke='white' />
<text id='prg-text' x='100' y='155' font-size='20' text-anchor='middle' fill='white'>50%</text>
</mask>
<rect id='rect' x='0' y='0' width='200' height='300' />
</svg>
<!-- just for demo -->
<div class='controls'>
<label>Set Progress:</label>
<input type='range' id='prg-input' min='0' max='100' value='50' />
</div>
If you are new to SVG you can refer to the MDN Docs (links provided below) for more information about the elements, their attributes and values.
SVG Mask Element
SVG Tutorial on Paths

Basic vertical SVG line

I cannot seem to find a good, working example / tutorial of how to draw a simple, vertical line which animates gradually on scroll from nothing to a full line.
I have the code below which draws a horizontal line, but I cannot seem to successfully change this to a vertical line that continues to animate.
HTML:
<svg id="mySVG">
<path fill="none" stroke="red" stroke-width="3" id="triangle" d="M1 0 L75 0"/>
</svg>
CSS:
#mySVG {
position: fixed;
top: 15%;
width: 400px;
height: 210px;
margin-left:0px;
}
JS:
<script>
// Get the id of the <path> element and the length of <path>
var triangle = document.getElementById("triangle");
var length = triangle.getTotalLength();
// The start position of the drawing
triangle.style.strokeDasharray = length;
// Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
triangle.style.strokeDashoffset = length;
// Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
window.addEventListener("scroll", myFunction);
function myFunction() {
var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
var draw = length * scrollpercent;
// Reverse the drawing (when scrolling upwards)
triangle.style.strokeDashoffset = length - draw;
}
</script>
It should just be a matter of making your line vertical, as follows:
<svg id="mySVG">
<path fill="none" stroke="red" stroke-width="3" id="triangle" d="M1 0 L1 75"/>
</svg>
What happens when you do that?
thanks for all your replies - I ended up using CSS transitions as this seem to work better.

Categories

Resources