我正在研究 SVG 中 click 的涟漪效应。涟漪效应的基本思想是每当用户点击 rect 标签时,就会根据点击的坐标和 rect 标签的尺寸创建一个圆形元素并进行动画处理。但是为了维持矩形内的圆,我使用了符号标签,它工作正常,但仅适用于没有 rx, ry 属性的矩形。主要问题是用圆角支撑矩形中的圆。
<!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>Ripple</title>
<style>
:root {
--radius: 0;
}
.ripple {
animation: ripple 600ms linear;
}
@keyframes ripple {
to {
r: var(--radius);
opacity: 0;
}
}
</style>
</head>
<body>
<svg id="svg" width="1300" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" focusable="false">
<symbol id="ripp" width="200" height="200">
<rect rx="100" x="0" y="0" id="rec" width="200" height="200"
style="fill:red;opacity:0.5"></rect>
</symbol>
<symbol x="60" y="260" id="ripp2" width="200" height="50">
<rect x="0" y="0" id="rec2" width="200" height="50"
style="fill:red;opacity:0.5"></rect>
</symbol>
<use xlink:href="#ripp" ></use>
<use xlink:href="#ripp2" ></use>
</svg>
<script>
const svg = document.getElementById('svg');
const rect = document.getElementById('rec');
const rect2 = document.getElementById('rec2');
setRipple(svg, rect, document.querySelector('#ripp'), 'red');
setRipple(svg, rect2, document.querySelector('#ripp2'), 'white');
function setRipple(svg, rect, symbolEle, color) {
function getactualcoor(elem, X, Y) {
let pt = elem.createSVGPoint();
pt.x = X;
pt.y = Y;
return pt.matrixTransform(elem.getScreenCTM().inverse());
}
rect.addEventListener('click', clickHandler);
function clickHandler(e) {
let radiusVariable = document.querySelector(':root');
let xminus = Number(symbolEle.getAttributeNS(null, 'x'));
let yminus = Number(symbolEle.getAttributeNS(null, 'y'));
let actualXminus = 0;
let actualYminus = 0;
if (xminus != null) {
actualXminus = xminus;
}
if (yminus != null) {
actualYminus = yminus;
}
let widthRect = rect.getBoundingClientRect().width;
let heightRect = rect.getBoundingClientRect().height;
let radiusAchieve = Math.sqrt(Math.pow(widthRect, 2) + Math.pow(heightRect, 2));
radiusVariable.style.setProperty('--radius', radiusAchieve);
let cooractual = getactualcoor(svg, e.clientX, e.clientY);
let initial = symbolEle.getElementsByClassName("ripple")[0];
if (initial) {
initial.remove()
}
let circ = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circ.setAttributeNS(null, 'cx', cooractual.x - actualXminus);
circ.setAttributeNS(null, 'cy', cooractual.y - actualYminus);
circ.style.pointerEvents = "none";
circ.classList.add('ripple');
circ.style.fill = color;
symbolEle.appendChild(circ);
}
}
</script>
</body>
</html>
答案 0 :(得分:0)
使用<mask>
。
<!-- define the path -->
<defs>
<rect rx="100" x="0" y="0" id="path-rec" width="200" height="200" />
</defs>
<!-- define the mask -->
<mask id="mask-rec" fill="white">
<use xlink:href="#path-rec"></use>
</mask>
<symbol id="ripp" width="200" height="200">
<g fill="red" opacity="0.5">
<use xlink:href="#path-rec" id="rec" ></use>
</g>
</symbol>
<!-- use the mask -->
<use xlink:href="#ripp" mask="url(#mask-rec)"></use>
<!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>Ripple</title>
<style>
:root {
--radius: 0;
}
.ripple {
animation: ripple 600ms linear;
}
@keyframes ripple {
to {
r: var(--radius);
opacity: 0;
}
}
</style>
</head>
<body>
<svg id="svg" width="1300" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" focusable="false">
<defs>
<rect rx="100" x="0" y="0" id="path-rec" width="200" height="200" />
</defs>
<mask id="mask-rec" fill="white">
<use xlink:href="#path-rec"></use>
</mask>
<symbol id="ripp" width="200" height="200">
<g fill="red" opacity="0.5">
<use xlink:href="#path-rec" id="rec" ></use>
</g>
</symbol>
<symbol x="60" y="260" id="ripp2" width="200" height="50">
<rect x="0" y="0" id="rec2" width="200" height="50"
style="fill:red;opacity:0.5"></rect>
</symbol>
<use xlink:href="#ripp" mask="url(#mask-rec)"></use>
<use xlink:href="#ripp2" ></use>
</svg>
<script>
const svg = document.getElementById('svg');
const rect = document.getElementById('rec');
const rect2 = document.getElementById('rec2');
setRipple(svg, rect, document.querySelector('#ripp'), 'red');
setRipple(svg, rect2, document.querySelector('#ripp2'), 'white');
function setRipple(svg, rect, symbolEle, color) {
function getactualcoor(elem, X, Y) {
let pt = elem.createSVGPoint();
pt.x = X;
pt.y = Y;
return pt.matrixTransform(elem.getScreenCTM().inverse());
}
rect.addEventListener('click', clickHandler);
function clickHandler(e) {
let radiusVariable = document.querySelector(':root');
let xminus = Number(symbolEle.getAttributeNS(null, 'x'));
let yminus = Number(symbolEle.getAttributeNS(null, 'y'));
let actualXminus = 0;
let actualYminus = 0;
if (xminus != null) {
actualXminus = xminus;
}
if (yminus != null) {
actualYminus = yminus;
}
let widthRect = rect.getBoundingClientRect().width;
let heightRect = rect.getBoundingClientRect().height;
let radiusAchieve = Math.sqrt(Math.pow(widthRect, 2) + Math.pow(heightRect, 2));
radiusVariable.style.setProperty('--radius', radiusAchieve);
let cooractual = getactualcoor(svg, e.clientX, e.clientY);
let initial = symbolEle.getElementsByClassName("ripple")[0];
if (initial) {
initial.remove()
}
let circ = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circ.setAttributeNS(null, 'cx', cooractual.x - actualXminus);
circ.setAttributeNS(null, 'cy', cooractual.y - actualYminus);
circ.style.pointerEvents = "none";
circ.classList.add('ripple');
circ.style.fill = color;
symbolEle.appendChild(circ);
}
}
</script>
</body>
</html>