SVG маска для фонового изображения
SVG маска для изображения. Удерживая левую кнопку мышки область маски будет расти и изображение вернется к своему исходному состоянию. Перемещая курсор мыши, область под ним будет отображать исходную картинку без маски.
HTML
<svg id="demo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="1600" height="900" viewBox="0 0 1600 900">
<defs>
<radialGradient id="maskGradient">
<stop offset="50%" stop-color="#fff"/>
<stop offset="100%" stop-color="#000"/>
</radialGradient>
<mask id="theMask">
<circle id="masker" r="150" fill="url(#maskGradient)" cx="800" cy="450" />
</mask>
</defs>
<image id="lines" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/314556/roomSketch.jpg" x="0" y="0" width="1600" height="900" />
<g id="maskReveal" mask="url(#theMask)" >
<image id="regular" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/314556/roomColor.jpg" x="0" y="0" width="1600" height="900" />
</g>
<circle id="ring" r="20" fill="none" stroke="#dc143c" stroke-width="2" cx="800" cy="450" />
<circle id="dot" r="4" fill="#dc143c" cx="800" cy="450" />
</svg>
<div id="instructions">
<svg id="dial" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<path id="progressRing" d="M50,10A40,40,0,1,1,10,50,40,40,0,0,1,50,10Z" fill="none" stroke="#fff" stroke-miterlimit="10" stroke-width="6"/>
<circle r="43" fill="none" stroke="#fff" cx="50" cy="50" stroke-width="2" opacity="0.5" />
<circle r="37" fill="none" stroke="#fff" cx="50" cy="50" stroke-width="2" opacity="0.5"/>
<text transform="translate(55 56)" text-anchor="start" font-size="20" fill="#fff">%</text>
<text id="counter" transform="translate(55 56)" text-anchor="end" font-size="20" fill="#fff">0</text>
</svg>
<p>Hover mouse to move mask around.</p>
<p>Hold & release mouse button to expand & contract mask.</p>
</div>
CSS
body {
padding: 0;
margin: 0;
font-family: "Signika", sans-serif;
background: #262626;
height: 100vh;
width: 100%;
overflow: hidden;
color: white;
}
p {
margin: 0;
text-align: center;
white-space: nowrap;
}
* {
box-sizing: border-box;
}
#demo {
cursor: none;
position: absolute;
}
#instructions {
position: absolute;
padding: 12px;
bottom: 20px;
background: rgba(0, 0, 0, 0.75);
left: 50%;
cursor: none;
padding-top: 100px;
user-select: none;
border-radius: 4px;
}
#dial {
position: absolute;
top: 0;
left: 50%;
}
JS
Дополнительно нужны две библиотеки:https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.4/TweenMax.min.js
https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/DrawSVGPlugin.min.js
Скрипт: console.clear();
var svg = document.querySelector("#demo");
var tl = new TimelineMax({onUpdate:onUpdate});
var pt = svg.createSVGPoint();
var data = document.querySelector(".tlProgress");
var counter = document.querySelector("#counter");
var ratio = 0.5625;
TweenMax.set("#instructions, #dial", {xPercent: -50});
TweenMax.set("#progressRing", {drawSVG:0});
tl.to("#masker", 2, {attr:{r:2400}, ease:Power2.easeIn});
tl.reversed(true);
function mouseHandler() {
tl.reversed(!tl.reversed());
}
function getPoint(evt){
pt.x = evt.clientX;
pt.y = evt.clientY;
return pt.matrixTransform(svg.getScreenCTM().inverse());
}
function mouseMove(evt) {
var newPoint = getPoint(evt);
TweenMax.set("#dot", {attr:{cx:newPoint.x, cy:newPoint.y}});
TweenMax.to("#ring, #masker", 0.88, {attr:{cx:newPoint.x, cy:newPoint.y}, ease:Power2.easeOut});
}
function onUpdate() {
var prog = (tl.progress() * 100);
TweenMax.set("#progressRing", {drawSVG:prog + "%"});
counter.textContent = prog.toFixed();
}
function newSize() {
var w = window.innerWidth ;
var h = window.innerHeight;
if (w > h * (16/9) ) {
TweenMax.set("#demo", { attr: { width: w, height: w * ratio } });
} else {
TweenMax.set("#demo", { attr: { width: h / ratio, height: h } });
}
var data = svg.getBoundingClientRect();
TweenMax.set("#demo", {x:w/2 - data.width/2});
TweenMax.set("#demo", {y:h/2 - data.height/2});
}
window.addEventListener("mousedown", mouseHandler);
window.addEventListener("mouseup", mouseHandler);
window.addEventListener("mousemove", mouseMove);
newSize();
window.addEventListener("resize", newSize);