I have been successful in animating stroke-dashoffset
with value as <length>
as folllowing
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', '0 0 400 200');
//make background
var fill1 = '#e6e6e6';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute('width', '400');
bg.setAttribute('height', '200');
bg.setAttribute('fill', fill1);
svg.appendChild(bg);
//wrapper dimension
var x = 20;
var y = 50;
var width = 200;
var height = 50;
let wrapper = document.createElementNS(svgns, 'rect');
wrapper.setAttribute('class', 'wrapper');
wrapper.setAttribute('id', 'wrapper');
wrapper.setAttribute('x', x);
wrapper.setAttribute('y', y);
wrapper.setAttribute('width', width);
wrapper.setAttribute('height', height);
wrapper.setAttribute('fill', 'none');
wrapper.setAttribute('stroke', 'black');
wrapper.setAttribute('stroke-width', '1');
svg.appendChild(wrapper);
let tube = document.createElementNS(svgns, 'line');
tube.setAttribute('class', 'tube');
tube.setAttribute('id', 'tube');
tube.setAttribute('x1', x);
tube.setAttribute('x2', x width);
tube.setAttribute('y1', y height / 2);
tube.setAttribute('y2', y height / 2);
tube.setAttribute('stroke', 'brown');
tube.setAttribute('stroke-width', '1');
svg.appendChild(tube);
var ln = document.querySelector("#tube");
var path = ln.getTotalLength();
ln.style.setProperty("--off", path 'px');
var pct = 0.60;
var pxl = path - (path * pct);
ln.style.setProperty('--offset', pxl);
ln.style.setProperty('--v1', (path / svg.viewBox.baseVal.width) * 100 '%');
ln.style.setProperty('--v2', (pxl / svg.viewBox.baseVal.width) * 100 '%');
var gridNum = 10;
var gridStart = width / gridNum;
var counter = gridStart;
for (var i = 0; i < gridNum; i ) {
let ln = document.createElementNS(svgns, 'line');
ln.setAttribute('class', 'axisLines' i);
ln.setAttribute('id', 'axisLines' i);
var x1 = x counter;
ln.setAttribute('x1', x1);
ln.setAttribute('x2', x counter);
ln.setAttribute('y1', y);
ln.setAttribute('y2', y height);
((gridNum / 2) - 1) == i ? ln.setAttribute('stroke', 'red') : ln.setAttribute('stroke', 'green');
ln.setAttribute('stroke-width', '1.5');
svg.appendChild(ln);
counter = counter gridStart;
let tl = document.createElementNS(svgns, 'title');
((gridNum / 2) - 1) == i ? tl.textContent = `Middle Coordinate ${x1-x},${y}` : tl.textContent = `Coordinate ${x1-x},${y}`;
svg.appendChild(tl);
ln.appendChild(tl);
}
.tube {
stroke-dasharray: var(--off);
stroke-dashoffset: var(--off);
animation: effect 4s ease-out infinite forwards;
}
@keyframes effect {
100% {
stroke-dashoffset: var(--offset);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
However, I am trying to figure out how can I calculate the exact %
value in css if I decide to use <percentage>
instead of value
.
I came to know from this post that percentages are calculated in respect to the current viewport, which I tried as
ln.style.setProperty('--v1', (path / svg.viewBox.baseVal.width) * 100 '%');
and
ln.style.setProperty('--v2', (pxl / svg.viewBox.baseVal.width) * 100 '%');
But passing on the above to CSS as following does not produce the same animation
.tube {
stroke-dasharray: var(--v1);
stroke-dashoffset: var(--v1);
animation: effect 4s ease-out infinite forwards;
}
@keyframes effect {
100% {
stroke-dashoffset: var(--v2);
}
}
CodePudding user response:
You need to calculate the normalised hypotenuse of the width and the height.
const svg = document.querySelector("svg");
// variable for the namespace
const svgns = "http://www.w3.org/2000/svg"
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', '0 0 400 200');
//make background
var fill1 = '#e6e6e6';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute('width', '400');
bg.setAttribute('height', '200');
bg.setAttribute('fill', fill1);
svg.appendChild(bg);
//wrapper dimension
var x = 20;
var y = 50;
var width = 200;
var height = 50;
let wrapper = document.createElementNS(svgns, 'rect');
wrapper.setAttribute('class', 'wrapper');
wrapper.setAttribute('id', 'wrapper');
wrapper.setAttribute('x', x);
wrapper.setAttribute('y', y);
wrapper.setAttribute('width', width);
wrapper.setAttribute('height', height);
wrapper.setAttribute('fill', 'none');
wrapper.setAttribute('stroke', 'black');
wrapper.setAttribute('stroke-width', '1');
svg.appendChild(wrapper);
let tube = document.createElementNS(svgns, 'line');
tube.setAttribute('class', 'tube');
tube.setAttribute('id', 'tube');
tube.setAttribute('x1', x);
tube.setAttribute('x2', x width);
tube.setAttribute('y1', y height / 2);
tube.setAttribute('y2', y height / 2);
tube.setAttribute('stroke', 'brown');
tube.setAttribute('stroke-width', '1');
svg.appendChild(tube);
var ln = document.querySelector("#tube");
var path = ln.getTotalLength();
ln.style.setProperty("--off", path 'px');
var pct = 0.60;
var pxl = path - (path * pct);
ln.style.setProperty('--offset', pxl);
ln.style.setProperty('--v1', (path / (Math.sqrt(svg.viewBox.baseVal.width ** 2 svg.viewBox.baseVal.height ** 2) / Math.sqrt(2))) * 100 '%');
ln.style.setProperty('--v2', (pxl / (Math.sqrt(svg.viewBox.baseVal.width ** 2 svg.viewBox.baseVal.height ** 2) / Math.sqrt(2))) * 100 '%');
var gridNum = 10;
var gridStart = width / gridNum;
var counter = gridStart;
for (var i = 0; i < gridNum; i ) {
let ln = document.createElementNS(svgns, 'line');
ln.setAttribute('class', 'axisLines' i);
ln.setAttribute('id', 'axisLines' i);
var x1 = x counter;
ln.setAttribute('x1', x1);
ln.setAttribute('x2', x counter);
ln.setAttribute('y1', y);
ln.setAttribute('y2', y height);
((gridNum / 2) - 1) == i ? ln.setAttribute('stroke', 'red') : ln.setAttribute('stroke', 'green');
ln.setAttribute('stroke-width', '1.5');
svg.appendChild(ln);
counter = counter gridStart;
let tl = document.createElementNS(svgns, 'title');
((gridNum / 2) - 1) == i ? tl.textContent = `Middle Coordinate ${x1-x},${y}` : tl.textContent = `Coordinate ${x1-x},${y}`;
svg.appendChild(tl);
ln.appendChild(tl);
}
.tube {
stroke-dasharray: var(--v1);
stroke-dashoffset: var(--v1);
animation: effect 4s ease-out infinite forwards;
}
@keyframes effect {
100% {
stroke-dashoffset: var(--v2);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>