Vertically centering part of svg content - javascript

I've been trying to center a collection of svg paths/text vertically in CSS / JS for quite a while with no luck. None of the solutions I've found here have worked so far. I have multiple < text > , < circle >, < rect >, although I don't think the type of content really matters.
The height is variable, so I have thought of 2 methods:
1) Transform via 50%. This is not working because you cannot transform a sub-set of content from a svg, from what I have found so far. The < g > tag was promising but I had no luck.
2) My second idea was to adjust the mask down via javascript once content is loaded. This, likewise, is not working.
All code is on code-pen and copied here as well: https://codepen.io/anon/pen/MmdWXB
HTML:
<div class="mask_group" id="mask_container">
<div class="text">
<svg>
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%" >
<rect class="cutout label" x="0" y="0" width="100%" height="100%"/>
<text class="label normal_font_weight" y="1em" dy="0em" x="50%">A</text>
<text class="label normal_font_weight" y="3em" dy="0em" x="50%">B</text>
<line class="label" x1="47%" y1="4.6em" x2="53%" y2="4.6em" style="stroke:rgb(255,0,0);stroke-width:1.5" />
<text class="label" y="7em" dy="0em" x="50%">C</text>
<text class="label" y="9em" id="final_text" dy="0em" x="50%">D</text>
</mask>
</defs>
<rect id="base" x="0" y="0" width="100%" height="100%"/>
</svg>
</div>
</div>
<div style="background-color:blue; width: 100%; height: 100%">
</div>
CSS:
html,body {
height: 100%;
}
.text {
position: relative;
/*top: 0;
left: 0;*/
width: 100%;
height: 100%;
margin-left: 0%;
/*z-index: 11; */
}
.mask_group {
position: fixed;
width: 100%;
height: 100%;
z-index: 10;
}
svg {
position: absolute;
width: 100%;
height: inherit;
}
svg text {
text-anchor: middle;
}
.cutout {
fill: white;
}
svg #base {
fill: #051E2A; /*#1F5773;*/
-webkit-mask: url(#mask);
mask: url(#mask);
}
/*Unused*/
.vert_center {
position: relative;
margin-top: 50%;
transform: translateY(-50%);
}
JS:
function body_loaded() {
var final_text = document.getElementById("final_text");
var position = final_text.getBoundingClientRect();
var bottom = position.bottom;
var mask_container = document.getElementById("mask_container");
var mask_position = mask_container.getBoundingClientRect();
var mask_height = mask_position.height;
var origin_y = (mask_height - bottom) / 2;
alert(origin_y);
var mask = document.getElementById("mask");
mask.style.y = origin_y;
}
Thanks ahead of time!

I'm not sure what you are attempting to do with the <mask>, so I am going to ignore it for now.
To vertically centre the SVG, just give it a fixed height and use the standard translate(-50%) trick. The only wrinkle is that you can't put the CSS transform on the <svg> element because transform has a different behavior in SVGs than it does in CSS. SVG transforms pre-date CSS transforms. So you just need to wrap the SVG in an HTML container and apply the transform to that instead.
I've set the height of the <svg> to 10em. Obviously you'll need to adjust that if you have more text. You could do that with JS using
svgElem.setAttribute("height", "10em");
But take it out of the CSS first obviously :)
html,body {
height: 100%;
}
.svg-wrapper {
position: absolute;
width: 100%;
top: 50%;
transform: translate(0, -50%);
}
.mask_group {
position: fixed;
width: 100%;
height: 100%;
z-index: 10;
}
svg {
width: 100%;
height: 10em;
fill: blue; /* default fill colour for contents */
}
svg text {
text-anchor: middle;
}
svg #base {
fill: #051E2A; /*#1F5773;*/
}
<div class="mask_group" id="mask_container">
<div class="svg-wrapper">
<svg>
<rect id="base" x="0" y="0" width="100%" height="100%"/>
<text class="label normal_font_weight" y="1em" dy="0em" x="50%">A</text>
<text class="label normal_font_weight" y="3em" dy="0em" x="50%">B</text>
<line class="label" x1="47%" y1="4.6em" x2="53%" y2="4.6em" style="stroke:rgb(255,0,0);stroke-width:1.5" />
<text class="label" y="7em" dy="0em" x="50%">C</text>
<text class="label" y="9em" id="final_text" dy="0em" x="50%">D</text>
</svg>
</div>
</div>
<div style="background-color:blue; width: 100%; height: 100%">
</div>

Related

Custom cursor not growing/scaling on hover (can't figure it out)

Hellol,I have a code for a custom cursor, and the cursor, which is a ball/circle, was supposed to grow/scale when hovering over a link, if you see the code below, this function is there, but it is not working, does anyone know what's wrong? Thank you in advance. Note, I am unable to create a snippet here. The code is from codepen: https://codepen.io/clementGir/pen/RQqvQx
<div class="cursor">
<div class="cursor__ball cursor__ball--big ">
<svg height="30" width="30">
<circle cx="15" cy="15" r="12" stroke-width="0"></circle>
</svg>
</div>
<div class="cursor__ball cursor__ball--small">
<svg height="10" width="10">
<circle cx="5" cy="5" r="4" stroke-width="0"></circle>
</svg>
</div>
</div>
<style>
body .cursor {
pointer-events: none;
}
body .cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 1000;
}
body .cursor__ball circle {
fill: #f7f8fa;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<script>
const $bigBall = document.querySelector('.cursor__ball--big');
const $smallBall = document.querySelector('.cursor__ball--small');
const $hoverables = document.querySelectorAll('a');
// Listeners
document.body.addEventListener('mousemove', onMouseMove);
for (let i = 0; i < $hoverables.length; i++) {
if (window.CP.shouldStopExecution(0)) break;
$hoverables[i].addEventListener('mouseenter', onMouseHover);
$hoverables[i].addEventListener('mouseleave', onMouseHoverOut);
}
// Move the cursor
window.CP.exitedLoop(0); function onMouseMove(e) {
TweenMax.to($bigBall, .4, {
x: e.clientX - 15,
y: e.clientY - 15
});
TweenMax.to($smallBall, .1, {
x: e.clientX - 5,
y: e.clientY - 7
});
}
// Hover an element
function onMouseHover() {
TweenMax.to($bigBall, .3, {
scale: 4
});
}
function onMouseHoverOut() {
TweenMax.to($bigBall, .3, {
scale: 1
});
}
</script>```
Growing cursor on hovering a link.
The codepen you are trying to copy links to external scripts and has been adapted to work inside codepen.
What I did to get the pen to work here (I think you only needed step 4):
For CSS & JS clicked down arrow top right, view compiled
Copy over all code
Settings>JS>External Scripts>Copy link into Stack Overflow snippet's external scripts
Removed 'window.CP' code junk which I assume is something to do with codepen and getting the window object of their sub-document
const $bigBall = document.querySelector('.cursor__ball--big');
const $smallBall = document.querySelector('.cursor__ball--small');
const $hoverables = document.querySelectorAll('.hoverable');
// Listeners
document.body.addEventListener('mousemove', onMouseMove);
for (let i = 0; i < $hoverables.length; i++) {
$hoverables[i].addEventListener('mouseenter', onMouseHover);
$hoverables[i].addEventListener('mouseleave', onMouseHoverOut);
}
// Move the cursor
function onMouseMove(e) {
TweenMax.to($bigBall, .4, {
x: e.pageX - 15,
y: e.pageY - 15 });
TweenMax.to($smallBall, .1, {
x: e.pageX - 5,
y: e.pageY - 7 });
}
// Hover an element
function onMouseHover() {
TweenMax.to($bigBall, .3, {
scale: 4 });
}
function onMouseHoverOut() {
TweenMax.to($bigBall, .3, {
scale: 1 });
}
body {
height: 100vh;
background: #010101;
cursor: none;
margin: 0;
display: flex;
font-family: monospace;
}
body h1,
body p,
body a {
color: #fff;
}
body a {
border-bottom: 2px solid #fff;
padding: 10px 0;
margin-top: 25px;
}
body .cursor {
pointer-events: none;
}
body .cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 1000;
}
body .cursor__ball circle {
fill: #f7f8fa;
}
body .left,
body .right {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
body .right {
background: #fff;
}
body .right a {
border-bottom: 2px solid #000;
}
body .right h1,
body .right p,
body .right a {
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<div class="cursor">
<div class="cursor__ball cursor__ball--big ">
<svg height="30" width="30">
<circle cx="15" cy="15" r="12" stroke-width="0"></circle>
</svg>
</div>
<div class="cursor__ball cursor__ball--small">
<svg height="10" width="10">
<circle cx="5" cy="5" r="4" stroke-width="0"></circle>
</svg>
</div>
</div>
<div class="left">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>
<div class="right">
<h1>Hello</h1>
<p>Check out this link:</p>
<a class="hoverable">Hover meh</a>
</div>

connecting divs with svg line

for (el of chart.children) {
i++
previous__element = chart.children[i - 1]
if (el.classList.contains('rule')) {
//pass
} else {
line = el.children[0].children[0]
pos1 = previous__element.children[2].getBoundingClientRect()
position1 = {
top: pos1.top,
left: pos1.left,
}
pos2 = el.children[2].getBoundingClientRect()
console.log(previous__element.children[2])
console.log(el.children[2])
position2 = {
top: pos2.top,
left: pos2.left,
}
line.setAttribute('x1', Math.trunc(pos1.left))
line.setAttribute('y1', Math.trunc(pos1.top))
line.setAttribute('x2', Math.trunc(pos1.left))
line.setAttribute('y2', Math.trunc(pos1.top))
line.setAttribute('stroke', 'white')
}
}
html that gets output:
For some reason this does not actually show the lines, when hovering over them in dev tools it shows the height and width is 0. I'm trying to get the line to connect to the markers in the elements.
In this example I use position relative/absolute on all the elements. I don't know if that fits your solution, but the core of the example is that the SVG document is in the background of all the boxes. So, all the lines could be placed in that one SVG document.
Maybe the reason why your lines are not showing up is that they mis the stroke-width or that your SVG element does not have a width and a height.
let chart = document.querySelector('#chart');
let poschart = chart.getBoundingClientRect();
let line = chart.querySelector('svg line');
let boxs = chart.querySelectorAll('div.box');
let pos1 = boxs[0].getBoundingClientRect();
line.setAttribute('x1', pos1.x+pos1.width/2-poschart.x);
line.setAttribute('y1', pos1.y+pos1.height/2-poschart.y);
let pos2 = boxs[1].getBoundingClientRect();
line.setAttribute('x2', pos2.x+pos2.width/2-poschart.x);
line.setAttribute('y2', pos2.y+pos2.height/2-poschart.y);
#chart {
position: relative;
width: 400px;
height: 300px;
margin: 10px 20px;
border: thin solid black;
}
#chart svg {
position: absolute;
}
.box {
position: absolute;
padding: .5em;
border: thin solid black;
background-color: white;
}
<div id="chart">
<svg viewBox="0 0 400 300" width="100%" height="100%">
<line stroke="black" stroke-width="2"/>
</svg>
<div class="box" style="left:50px;top:180px">Box 1</div>
<div class="box" style="left:310px;top:100px">Box 2</div>
</div>

Mousemove and Hover Jquery effect to Pure Javascript or VueJS event

I have a VueJS component which is a svg map image of the united states. I previously used jquery to create hover effects to display the information bubble. I am trying to convert this to a pure Javascript solution. It seems a click event is the easiest to implement given vuejs mousemove seems to be less reliable. I have added the click event in method and I am trying to capture the SVG path location and steal the top and left position to enable the info box there. I have tried this.offsettop and this.offsetleft but they return undefined.
Jquery code I am trying to convert:
$("path, circle").hover(function(e) {
$('#info-box').css('display','block');
$('#info-box').html($(this).data('info'));
});
$("path, circle").mouseleave(function(e) {
$('#info-box').css('display','none');
});
$(document).mousemove(function(e) {
$('#info-box').css('top',e.pageY-$('#info-box').height()-30);
$('#info-box').css('left',e.pageX-($('#info-box').width())/2);
}).mouseover();
var ios = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if(ios) {
$('a').on('click touchend', function() {
var link = $(this).attr('href');
window.open(link,'_blank');
return false;
});
}
VueJS Component
<template id="geomap-assignments">
<v-card class="pa-4 ma-3 rounded-lg" min-height="500px">
<div class="card-title-docs">
<h4 class="card-header">Assignments</h4>
<h5 class="card-sub-header"></h5>
</div>
<div class="map-container">
<div id="info-box"></div>
<?xml version="1.0" encoding="utf-8" ?>
<svg xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="us-map" preserveAspectRatio="xMinYMin meet" sodipodi:docname="Republican_Party_presidential_primaries_results,_2016.svg" inkscape:version="0.91 r13725" x="0px" y="0px" width="959px" height="593px" viewBox="174 100 959 593" enable-background="new 174 100 959 593" xml:space="preserve">
<sodipodi:namedview bordercolor="#666666" objecttolerance="10" pagecolor="#ffffff" borderopacity="1" gridtolerance="10" guidetolerance="10" inkscape:cx="509.19152" inkscape:cy="282.2353" inkscape:zoom="1.2137643" showgrid="false" id="namedview71" inkscape:current-layer="g5" inkscape:window-maximized="1" inkscape:window-y="-8" inkscape:window-x="-8" inkscape:pageopacity="0" inkscape:window-height="1017" inkscape:window-width="1920" inkscape:pageshadow="2">
</sodipodi:namedview>
<g id="g5">
<path id="HI" data-info="<div>State: Hawaii</div><div>Capital: Honolulu</div>" fill="#D3D3D3" d="M407.1,619.3l1.9-3.6l2.3-0.3l0.3,0.8l-2.1,3.1H407.1z M417.3,615.6l6.1,2.6l2.1-0.3l1.6-3.9 l-0.6-3.4l-4.2-0.5l-4,1.8L417.3,615.6z M448,625.6l3.7,5.5l2.4-0.3l1.1-0.5l1.5,1.3l3.7-0.2l1-1.5l-2.9-1.8l-1.9-3.7l-2.1-3.6 l-5.8,2.9L448,625.6z M468.2,634.5l1.3-1.9l4.7,1l0.6-0.5l6.1,0.6l-0.3,1.3l-2.6,1.5l-4.4-0.3L468.2,634.5z M473.5,639.7l1.9,3.9 l3.1-1.1l0.3-1.6l-1.6-2.1l-3.7-0.3V639.7z M480.5,638.5l2.3-2.9l4.7,2.4l4.4,1.1l4.4,2.7v1.9l-3.6,1.8l-4.8,1l-2.4-1.5 L480.5,638.5z M497.1,654.1l1.6-1.3l3.4,1.6l7.6,3.6l3.4,2.1l1.6,2.4l1.9,4.4l4,2.6l-0.3,1.3l-3.9,3.2l-4.2,1.5l-1.5-0.6l-3.1,1.8 l-2.4,3.2l-2.3,2.9l-1.8-0.2l-3.6-2.6l-0.3-4.5l0.6-2.4l-1.6-5.7l-2.1-1.8l-0.2-2.6l2.3-1l2.1-3.1l0.5-1l-1.6-1.8L497.1,654.1z" />
<path id="OK" data-info="<div>State: Oklahoma</div><div>Capital: Oklahoma City</div>" fill="#D3D3D3" d="M549.3,422.6l-10.7-0.5l-6.4-0.5l0.3,0.2l-0.7,10.4l22,1.4l32.1,1.3l-2.3,24.4l-0.5,17.8l0.2,1.6 l4.3,3.7l2.1,1.1l0.7-0.2l0.7-2.1l1.4,1.8h2.1v-1.4l2.7,1.4l-0.5,3.9l4.1,0.2l2.5,1.1l4.1,0.7l2.5,1.8l2.3-2.1l3.4,0.7l2.5,3.4h0.9 v2.3l2.3,0.7l2.3-2.3l1.8,0.7h2.5l0.9,2.5l4.8,1.8l1.4-0.7l1.8-4.1h1.1l1.1,2.1l4.1,0.7l3.7,1.4l3,0.9l1.8-0.9l0.7-2.5h4.3l2.1,0.9 l2.7-2.1h1.1l0.7,1.6h4.1l1.6-2.1l1.8,0.5l2.1,2.5l3.2,1.8l3.2,0.9l1.9,1.1l-0.4-37.2l-1.4-11l-0.2-8.9l-1.4-6.5l-0.8-7.2l-0.1-3.8 l-12.1,0.3l-46.4-0.5l-45-2.1L549.3,422.6z" />
<path id="KS" data-info="<div>State: Kansas</div><div>Capital: Topeka</div>" fill="#D3D3D3" d="M677.4,425.1l-12.6,0.2l-46.1-0.5l-44.6-2.1l-24.6-1.3l4.1-64.7l21.8,0.8l40.5,1.4l44.1,0.5h5.1 l3.2,3.2l2.8,0.2l0.9,1.1v2l-1.8,1.6l-0.5,2.6l2.2,3.6l2.5,3.1l2.5,2l1.1,11.2L677.4,425.1z" />
<path id="LA" data-info="<div>State: Louisiana</div><div>Capital: Baton Rouge</div>" fill="#D3D3D3" d="M776.2,573l-1-2.6l-1.1-3.1l-3.3-3.5l0.9-6.8l-0.1-1.1l-1.3,0.3l-8.2,0.9l-25,0.5l-0.7-2.4l0.9-8.5 l3.3-5.9l5-8.7l-0.6-2.4l1.3-0.7l0.5-2l-2.3-2.1l-0.1-1.9l-1.8-4.3l-0.5-5.9l-9.7,0.1l-19.2,0.9l-22.2,0l0,9.6l0.7,9.4l0.7,3.9 l2.5,4.1l0.9,5l4.3,5.5l0.2,3.2l0.7,0.7l-0.7,8.5l-3,5l1.6,2.1l-0.7,2.5l-0.7,7.3l-1.4,3.2l0.1,3.6l4.7-1.5l8.1-0.3l10.3,3.6 l6.5,1.1l3.7-1.5l3.2,1.1l3.2,1l0.8-2.1l-3.2-1.1l-2.6,0.5l-2.7-1.6c0,0,0.2-1.3,0.8-1.5c0.6-0.2,3.1-1,3.1-1l1.8,1.5l1.8-1 l3.2,0.6l1.5,2.4l0.3,2.3l4.5,0.3l1.8,1.8l-0.8,1.6l-1.3,0.8l1.6,1.6l8.4,3.6l3.6-1.3l1-2.4l2.6-0.6l1.8-1.5l1.3,1l0.8,2.9 l-2.3,0.8l0.6,0.6l3.4-1.3l2.3-3.4l0.8-0.5l-2.1-0.3l0.8-1.6l-0.2-1.5l2.1-0.5l1.1-1.3l0.6,0.8c0,0-0.2,3.1,0.6,3.1 c0.8,0,4.2,0.6,4.2,0.6l4,1.9l1,1.5h2.9l1.1,1l2.3-3.1v-1.5h-1.3l-3.4-2.7l-5.8-0.8l-3.2-2.3l1.1-2.7l2.3,0.3l0.2-0.6l-1.8-1v-0.5 h3.2l1.8-3.1l-1.3-1.9l-0.3-2.7l-1.5,0.2l-1.9,2.1l-0.6,2.6l-3.1-0.6l-1-1.8l1.8-1.9l2-1.8L776.2,573z" />
<path id="VA" data-info="<div>State: Virginia</div><div>Capital: Richmond</div>" fill="#D3D3D3" d="M1002.9,369.2l-0.1-1.9l6.5-2.5l-0.8,3.2l-2.9,3.8l-0.4,4.6l0.5,3.4l-1.8,5l-2.2,1.9l-1.5-4.6 l0.4-5.4l1.6-4.2L1002.9,369.2z M1005.2,397.5L947,410.1l-37.4,5.3l-6.7-0.4l-2.6,1.9l-7.3,0.2l-8.4,1l-8.9,1l8.5-4.9l0-2.1 l1.5-2.1l10.6-11.5l3.9,4.5l3.8,1l2.5-1.1l2.2-1.3l2.5,1.3l3.9-1.4l1.9-4.6l2.6,0.5l2.9-2.1l1.8,0.5l2.8-3.7l0.3-2.1l-1-1.3l1-1.9 l5.3-12.3l0.6-5.7l1.2-0.5l2.2,2.4l3.9-0.3l1.9-7.6l2.8-0.6l1-2.7l2.6-2.3l1.3-2.3l1.5-3.4l0.1-5.1l9.8,3.8 c0.7,0.3,0.7-4.8,0.7-4.8l4.1,1.4l-0.5,2.6l8.2,2.9l1.3,1.8l-0.9,3.7l-1.3,1.3l-0.5,1.7l0.5,2.4l2,1.3l3.9,1.4l2.9,1l4.9,0.9 l2.2,2.1l3.2,0.4l0.9,1.2l-0.4,4.7l1.4,1.1l-0.5,1.9l1.2,0.8l-0.2,1.4l-2.7-0.1l0.1,1.6l2.3,1.5l0.1,1.4l1.8,1.8l0.5,2.5l-2.6,1.4 l1.6,1.5l5.8-1.7L1005.2,397.5z" />
<g id="DC">
<path id="path58" fill="#D3D3D3" d="M975.8,353.8l-1.1-1.6l-1-0.8l1.1-1.6l2.2,1.5L975.8,353.8z" />
<circle id="circle60" data-info="<div>Washington DC</div>" fill="#D3D3D3" stroke="#FFFFFF" stroke-width="1.5" cx="975.3" cy="351.8" r="5" />
</g>
</g>
<path id="path67" fill="none" stroke="#A9A9A9" stroke-width="2" d="M385,593v55l36,45 M174,525h144l67,68h86l53,54v46" />
</svg>
</div>
</v-card>
</template>
<script>
Vue.component('geomap-assignments', {
template: '#geomap-assignments',
methods: {
activateCaption: function (event) {
// `event` is the native DOM event
if (event) {
const left = this.offsetTop
const top = this.offsetTop
alert("LEFT" + left + "RIGHT" + top);
}
}
},
data() {
return {
documents: [
]
}
}
})
</script>
<style scoped>
.card-title-docs {
margin: 20px 20px;
}
.card-header {
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
color: #515151;
}
.card-sub-header {
font-size: .8rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: .7px;
color: #7f818d;
}
.map-container{
position:relative;
width: 100%;
height: 100%;
}
#us-map {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
path:hover, circle:hover {
stroke: #002868 !important;
stroke-width: 2px;
stroke-linejoin: round;
fill: #002868 !important;
cursor: pointer;
}
#path67 {
fill: none !important;
stroke: #A9A9A9 !important;
cursor: default;
}
#info-box {
display: none;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
background-color: #ffffff;
border: 2px solid #BF0A30;
border-radius: 5px;
padding: 5px;
font-family: arial;
}
</style>
'''
The solution was found in the comments on the question.
In summary, the issue was understanding how to position the #info-box element. Using the getBoundingClientRect() function, we can get the position of any element relative to the entire document. To get the position of the clicked path element, simply subtract the top and left of the #us-map from the top and left of the path. This will give the position for the top left corner of the path, relative to the containing element. We can then use that to position the #info-box.

Javscript to dynamically build HTML/SVG for mobile view

I have a full screen SVG image/mask reveal; it works great on desktop but it doesn't scale/fit on mobile devices. So im guessing the best solution would be to dynamically build the SVG and SVG container depending on screen width and have a mobile & desktop build. So i'm looking for advice and the best solution and if someone could point me in the right direction or know of an example I can look at.
// DRAW SVG MASK /////////////////////////////
var svg = document.querySelector("#svg__bg");
var tl = new gsap.timeline({ onUpdate: onUpdate });
var pt = svg.createSVGPoint();
var ratio = 0.5625;
tl.to("#masker", {duration: 2, attr: {r: 2400}, ease: "power2.in" });
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);
gsap.set("#dot", { cx: newPoint.x, cy: newPoint.y });
gsap.to("#ring, #masker", {duration: 0.88, attr: { cx: newPoint.x, cy: newPoint.y }, ease: "power2.out" });
}
function onUpdate() {
var prog = (tl.progress() * 100);
}
function newSize() {
var w = window.innerWidth;
var h = window.innerHeight;
if (w > h * (16 / 9)) {
gsap.set("#svg__bg", { attr: { width: w, height: w * ratio } });
} else {
gsap.set("#svg__bg", {
attr: {
width: h / ratio,
height: h
}
});
}
var data = svg.getBoundingClientRect();
gsap.set("#svg__bg", {
x: w / 2 - data.width / 2
});
gsap.set("#svg__bg", {
y: h / 2 - data.height / 2
});
}
window.addEventListener("mousedown", mouseHandler);
window.addEventListener("mouseup", mouseHandler);
window.addEventListener("mousemove", mouseMove);
newSize();
window.addEventListener("resize", newSize);
#import url('https://fonts.googleapis.com/css?family=Montserrat:700&display=swap');
body {
min-height: 100vh;
background-color: #1F242D;
cursor: none;
overflow: hidden;
font-family: 'Montserrat', sans-serif;
}
.intro-svg {
position: relative;
padding: 0;
margin: 0;
width: 100%;
min-height: 100vh;
height: calc(var(--vh, 1vh) * 100);
overflow: hidden;
z-index: 1;
}
.svg__container {
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
}
.svg__image {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
cursor: none;
}
.text-svg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
cursor: none;
z-index:2;
}
.impact-text {
font-size: 7em;
line-height: 1.2;
text-transform: uppercase;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<div class="intro-svg">
<div class="svg__container">
<svg id="svg__bg" class="svg__image" xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="1600" height="900" viewBox="0 0 1600 900">
<defs>
<radialGradient id="mask-gradient">
<stop offset="80%" stop-color="#fff"/><stop offset="100%" stop-color="#000" />
</radialGradient>
<mask id="the-mask">
<circle id="masker" r="250" fill="url(#mask-gradient)" cx="800" cy="450">
</circle>
</mask>
<mask id="mask-text" width="100" height="100" x="0" y="0">
<text id="masker" class="impact-text row-1" fill="none" stroke="#fff" stroke-width="3" x="10.1%" y="42%">A</text>
<text id="masker" class="impact-text row-2" fill="white" x="10%" y="55%">Digital</text>
<text id="masker" class="impact-text row-3" fill="white" x="10%" y="68%">Designer</text>
</mask>
</defs>
<image id="lines" xlink:href="https://i.imgur.com/1TQRj56.jpg" x="0" y="0" width="1600" height="900" />
<g id="mask-reveal" mask="url(#the-mask)">
<image id="regular" xlink:href="https://i.imgur.com/7VtEKv3.jpg" x="0" y="0" width="1600" height="900" />
</g>
<g mask="url(#mask-text)">
<image id="text-before" xlink:href="https://i.imgur.com/7VtEKv3.jpg" x="0" y="0" width="1600" height="900" />
</g>
<circle id="ring" r="20" fill="none" stroke="#D74A53" stroke-width="2" cx="800" cy="450" />
<circle id="dot" r="4" fill="#D74A53" cx="800" cy="450"/>
</svg>
</div>
</div>
just add
#svg__bg {
width: 100%;
height:auto;
}
andchange them with media query
don't forget to change
<svg id="svg__bg" class="svg__image" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1600 900">
without width="1600" height="900"

SVG filter not working when imbedded with JavaScript

I have been trying to get the blur effect to work when creating the elements and imbedding them with JavaScript. I cannot figure out why the blur will not show up. I have two fiddles, one with the standard HTML & CSS and the other using JavaScript. If anyone wants to check them out and offer an explanation as to what I am doing wrong I would really appreciate it.
HTML & CSS Version (Works)
https://jsfiddle.net/aaronbalthaser/xampLtnr/
HTML:
<div id="container">
<img src="http://lorempixel.com/300/250/sports/" width="300" height="250" />
<svg width="300" height="60" viewbox="0 0 300 60">
<defs>
<filter id="blur">
<fegaussianblur in="SourceGraphic" stddeviation="5" />
</filter>
</defs>
<image filter="url(#blur)" xlink:href="http://lorempixel.com/300/250/sports/" x="0" y="-190" height="250px" width="300px" />
</svg>
</div>
CSS:
#container {
position: relative;
width: 300px;
height: 250px;
margin: 0 auto;
position: relative;
}
svg {
position: absolute;
bottom: 0;
left: 0;
}
JavaScript Version (Doesn't Work)
https://jsfiddle.net/aaronbalthaser/Lbnkfn02/
HTML:
<div id="container">
<img src="http://lorempixel.com/300/250/sports/" width="300" height="250" />
</div>
CSS:
#container {
position: relative;
width: 300px;
height: 250px;
margin: 0 auto;
position: relative;
}
svg {
position: absolute;
bottom: 0;
left: 0;
}
JS:
var width = 300;
var height = 250;
var viewbox = "0 0 300 60";
var namespace = 'http://www.w3.org/2000/svg'
var path = 'http://lorempixel.com/300/250/sports/';
var container = document.getElementById('container');
var body = document.body;
var svg = document.createElementNS(namespace,'svg');
svg.setAttribute('width', width);
svg.setAttribute('height', 60);
svg.setAttribute('viewBox', viewbox);
var defs = document.createElementNS(namespace, 'defs');
var filter = document.createElementNS(namespace, 'filter');
filter.setAttribute('id', 'blur');
var feGaussianBlur = document.createElementNS(namespace, 'feGaussianBlur');
feGaussianBlur.setAttribute('in', 'SourceGraphic');
feGaussianBlur.setAttribute('stdDeviation', '5');
var image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
image.setAttribute('filter', 'url(#blur)');
image.setAttribute('xlink:href', path);
image.setAttribute('x', + '0');
image.setAttribute('y', + '-190');
image.setAttribute('height', height + 'px');
image.setAttribute('width', width + 'px');
filter.appendChild(feGaussianBlur);
defs.appendChild(filter);
svg.appendChild(defs);
svg.appendChild(image);
container.appendChild(svg);
console.log(container);
image.setAttribute('xlink:href', path);
should be
image.setAttributeNS("http://www.w3.org/1999/xlink", 'xlink:href', path);
https://jsfiddle.net/Lbnkfn02/2/

Categories