D3 - add shadow ONLY at the top of bubble chart - d3.js
I am using D3.js to draw bubble graph.
I want to add shadow effect at the top of SVG circle.
But when I use filter to add shadow then shadow is added to all the sides.
How can I just have it at the top like:
Expected:
Current:
Here is the html file code:
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<style>
.inner-point{
width: 20px;
height: 10px;
background: white;
}
.header{
//margin-top:100px;
}
#left,#right{
border:2px solid #78A9A9;
}
#right{
border-left: none;
}
.head-top{
color:#78A9A9;
}
.right{
text-align: center;
margin-right: -17px;
width: 460px;
}
.text-center{
text-align: center;
padding-right: 0px;
padding-left: 0px;
}
.link{
position: relative;
margin: 396px;
bottom: 0px;
color:#A37512;
}
.left-circle,.right-circle{
padding-left: 0px;
padding-right: 0px;
}
</style>
</head>
<body cz-shortcut-listen="true">
<div class="header">
<div class="left-circle col-sm-5">
<svg id="left" width="458" height="500">
<defs>
<linearGradient id="gradient1" x1="65%" y1="100%" x2="54%" y2="44%" spreadMethod="pad">
<stop offset="0%" stop-color="#0365C0" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#51A7F9" stop-opacity="1"></stop>
</linearGradient>
</defs>
<defs>
<linearGradient id="gradient2" x1="65%" y1="100%" x2="54%" y2="44%" spreadMethod="pad">
<stop offset="0%" stop-color="#773F9B" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#885CB2" stop-opacity="1"></stop>
</linearGradient>
</defs>
<defs>
<filter id="drop-shadow" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur>
<feOffset in="blur" dx="0" dy="0" result="offsetBlur"></feOffset>
<feMerge><feMergeNode in="offsetBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge></filter>
</defs>
<g class="node" transform="translate(197.1414719461316,229)">
<circle class="shadowed" id="Provider25S1511" r="131.42764796408775" onclick="demo('Provider25S151','Amount of Spend $49979.62',1,262.14147194613156,327);" stroke="#0365C0" stroke-width="1" style="filter: url("#drop-shadow"); fill: url("#gradient1");"></circle>
<clipPath id="clip-Provider25S151"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Provider25S151">
</use></clipPath>
</g>
</svg>
</div>
</div>
</body></html>
In the <feOffset> element in the filter, make the dy value negative by a little to move the shadow up a bit. Negative values move it up, positive values move it down.
So change
<feOffset in="blur" dx="0" dy="0" result="offsetBlur"></feOffset>
to (for example)
<feOffset in="blur" dx="0" dy="-4" result="offsetBlur"></feOffset>
<svg id="left" width="458" height="500">
<defs>
<linearGradient id="gradient1" x1="65%" y1="100%" x2="54%" y2="44%" spreadMethod="pad">
<stop offset="0%" stop-color="#0365C0" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#51A7F9" stop-opacity="1"></stop>
</linearGradient>
</defs>
<defs>
<linearGradient id="gradient2" x1="65%" y1="100%" x2="54%" y2="44%" spreadMethod="pad">
<stop offset="0%" stop-color="#773F9B" stop-opacity="1"></stop>
<stop offset="100%" stop-color="#885CB2" stop-opacity="1"></stop>
</linearGradient>
</defs>
<defs>
<filter id="drop-shadow" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur>
<feOffset in="blur" dx="0" dy="-4" result="offsetBlur"></feOffset>
<feMerge><feMergeNode in="offsetBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge></filter>
</defs>
<g class="node" transform="translate(197.1414719461316,229)">
<circle class="shadowed" id="Provider25S1511" r="131.42764796408775" onclick="demo('Provider25S151','Amount of Spend $49979.62',1,262.14147194613156,327);" stroke="#0365C0" stroke-width="1" style="filter: url("#drop-shadow"); fill: url("#gradient1");"></circle>
<clipPath id="clip-Provider25S151"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Provider25S151">
</use></clipPath>
</g>
</svg>
Related
SVG animate gradient along path
I have the following svg that i would like to animate. I would like the red part moves along the path up to the end (so from the top right side to the left bottom side) : The problem is : obviously is quite impossible to have a gradient following a path. Here is my code so far : <svg id="fil" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 783.53 362"> <defs> <style> .cls-3{ fill: none; stroke-miterlimit:10; stroke-width:3px; } </style> <linearGradient id="light" x1="100%" y1="100%"> <stop offset="70%" stop-color="#3E3E3E"> <!-- <animate attributeName="stop-color" to="#CF4B59" from="#3E3E3E" dur="0.5s" fill="freeze" /> --> </stop> <stop offset="100%" stop-color="#CF4B59"> <!-- <animate attributeName="stop-color" from="#CF4B59" to="#3E3E3E" dur="0.5s" fill="freeze" /> --> </stop> </linearGradient> </defs> <g id="Calque_2" data-name="Calque 2"> <g id="Calque_1-2" data-name="Calque 1"> <g class="cls-2"> <path class="cls-3" id="base" d="M656.89,8.93c0,48,7.42,124.9,64.45,125.92a115.56,115.56,0,0,0,53.83-12.28c8.35-4.2,16.35-9.59,21.84-17.15s8.15-17.62,5.25-26.51c-3.12-9.53-12.16-16.28-21.87-18.83-61.57-16.19-142.83,57.7-139.63,119.4,1.23,23.69,16.72,41.59,37.61,51.29,27,12.55,60.55,13.36,89.45,8.06,12.25-2.25,25.82-5.25,37.26-10.44,12.63-5.72,32.28-20.08,28.88-36.64a18,18,0,0,0-15.63-14.59c-10.28-1.4-19.14,3.57-26.76,10-16.18,13.66-29.34,30.65-44.7,45.2a359.34,359.34,0,0,1-49.33,39.08A356.65,356.65,0,0,1,638.08,303c-35.77,14.83-90.88,29.56-123.22-.47-11.61-10.78-17.61-26.71-18.41-42.53-1.07-21.19,4.41-54.95,30-59.28,36.67-6.2,78.65,49.05,86.38,79.36,8.2,32.14-5.44,70.78-35.75,84.26-28.8,12.81-63.93,0-85.8-22.72-23.52-24.41-18.59-55.9-36.07-82.56-16-24.39-41.3-23.5-66.77-24.62" transform="translate(-52.32 -8.93)" stroke="url(#light)"/> </g> </g> </g> </svg> I tried to use "animate" to make it move along the path, but it's a vertical gradient which is applied and goes from the top to the bottom and not a gradient which follows the path. I had other ideas to overcome this : Maybe by using a second path which would be the same shape than the first one but with inverted gradient so I could make it slide along the initial path maybe Or, I could use opacity to make the final path appear but i'm not sure i will be able to make the red part move in this way... If you have some ideas to make the red part move from the top right to the bottom left it would help me a lot!
Question I would like the red part moves along the path up to the end (so from the top right side to the left bottom side) : Consider using fill-line animation with stroke-dashoffset. For clarity, I placed exactly the same curve below which will show the route of filling the line with color If this indication of the motion path is not necessary, simply remove the path id = "trace" <svg id="fil" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 783.53 362"> <defs> <style> .cls-3{ fill: none; stroke-miterlimit:10; stroke-width:3px; stroke:#E7E7E7; } #base { fill: none; stroke:crimson; stroke-width:3px; stroke-dashoffset:1732; stroke-dasharray:1732; animation: fillStroke 10s linear forwards; } #keyframes fillStroke { to {stroke-dashoffset:0;} } </style> </defs> <g transform="translate(-352.32 -8.93)"> <path id="trace" class="cls-3" d="M656.89,8.93c0,48,7.42,124.9,64.45,125.92a115.56,115.56,0,0,0,53.83-12.28c8.35-4.2,16.35-9.59,21.84-17.15s8.15-17.62,5.25-26.51c-3.12-9.53-12.16-16.28-21.87-18.83-61.57-16.19-142.83,57.7-139.63,119.4,1.23,23.69,16.72,41.59,37.61,51.29,27,12.55,60.55,13.36,89.45,8.06,12.25-2.25,25.82-5.25,37.26-10.44,12.63-5.72,32.28-20.08,28.88-36.64a18,18,0,0,0-15.63-14.59c-10.28-1.4-19.14,3.57-26.76,10-16.18,13.66-29.34,30.65-44.7,45.2a359.34,359.34,0,0,1-49.33,39.08A356.65,356.65,0,0,1,638.08,303c-35.77,14.83-90.88,29.56-123.22-.47-11.61-10.78-17.61-26.71-18.41-42.53-1.07-21.19,4.41-54.95,30-59.28,36.67-6.2,78.65,49.05,86.38,79.36,8.2,32.14-5.44,70.78-35.75,84.26-28.8,12.81-63.93,0-85.8-22.72-23.52-24.41-18.59-55.9-36.07-82.56-16-24.39-41.3-23.5-66.77-24.62" /> <g class="cls-2"> <path id="base" d="M656.89,8.93c0,48,7.42,124.9,64.45,125.92a115.56,115.56,0,0,0,53.83-12.28c8.35-4.2,16.35-9.59,21.84-17.15s8.15-17.62,5.25-26.51c-3.12-9.53-12.16-16.28-21.87-18.83-61.57-16.19-142.83,57.7-139.63,119.4,1.23,23.69,16.72,41.59,37.61,51.29,27,12.55,60.55,13.36,89.45,8.06,12.25-2.25,25.82-5.25,37.26-10.44,12.63-5.72,32.28-20.08,28.88-36.64a18,18,0,0,0-15.63-14.59c-10.28-1.4-19.14,3.57-26.76,10-16.18,13.66-29.34,30.65-44.7,45.2a359.34,359.34,0,0,1-49.33,39.08A356.65,356.65,0,0,1,638.08,303c-35.77,14.83-90.88,29.56-123.22-.47-11.61-10.78-17.61-26.71-18.41-42.53-1.07-21.19,4.41-54.95,30-59.28,36.67-6.2,78.65,49.05,86.38,79.36,8.2,32.14-5.44,70.78-35.75,84.26-28.8,12.81-63.93,0-85.8-22.72-23.52-24.41-18.59-55.9-36.07-82.56-16-24.39-41.3-23.5-66.77-24.62" > </path> </g> </g> </svg> Gradient animation option Instead of filling with color as the length of the curve increases, a gradient will perform this function <svg id="fil" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 783.53 362"> <defs> <style> .cls-3{ fill: none; stroke-miterlimit:10; stroke-width:3px; stroke:#E7E7E7; } #base { fill: none; stroke:url(#light); stroke-width:3px; stroke-dashoffset:1732; stroke-dasharray:1732; animation: fillStroke 10s linear forwards; } #keyframes fillStroke { to {stroke-dashoffset:0;} } </style> <linearGradient id="light" x1="100%" y1="100%"> <stop offset="50%" stop-color="#CF4B59"> <!-- <animate attributeName="stop-color" from="#CF4B59" to="#3E3E3E" dur="10s" fill="freeze" /> --> </stop> <stop offset="100%" stop-color="#3E3E3E"> <!-- <animate attributeName="stop-color" to="#CF4B59" from="#3E3E3E" dur="10s" fill="freeze" /> --> </stop> </linearGradient> </defs> <g transform="translate(-352.32 -8.93)"> <path class="cls-3" d="M656.89,8.93c0,48,7.42,124.9,64.45,125.92a115.56,115.56,0,0,0,53.83-12.28c8.35-4.2,16.35-9.59,21.84-17.15s8.15-17.62,5.25-26.51c-3.12-9.53-12.16-16.28-21.87-18.83-61.57-16.19-142.83,57.7-139.63,119.4,1.23,23.69,16.72,41.59,37.61,51.29,27,12.55,60.55,13.36,89.45,8.06,12.25-2.25,25.82-5.25,37.26-10.44,12.63-5.72,32.28-20.08,28.88-36.64a18,18,0,0,0-15.63-14.59c-10.28-1.4-19.14,3.57-26.76,10-16.18,13.66-29.34,30.65-44.7,45.2a359.34,359.34,0,0,1-49.33,39.08A356.65,356.65,0,0,1,638.08,303c-35.77,14.83-90.88,29.56-123.22-.47-11.61-10.78-17.61-26.71-18.41-42.53-1.07-21.19,4.41-54.95,30-59.28,36.67-6.2,78.65,49.05,86.38,79.36,8.2,32.14-5.44,70.78-35.75,84.26-28.8,12.81-63.93,0-85.8-22.72-23.52-24.41-18.59-55.9-36.07-82.56-16-24.39-41.3-23.5-66.77-24.62" /> <g class="cls-2"> <path id="base" d="M656.89,8.93c0,48,7.42,124.9,64.45,125.92a115.56,115.56,0,0,0,53.83-12.28c8.35-4.2,16.35-9.59,21.84-17.15s8.15-17.62,5.25-26.51c-3.12-9.53-12.16-16.28-21.87-18.83-61.57-16.19-142.83,57.7-139.63,119.4,1.23,23.69,16.72,41.59,37.61,51.29,27,12.55,60.55,13.36,89.45,8.06,12.25-2.25,25.82-5.25,37.26-10.44,12.63-5.72,32.28-20.08,28.88-36.64a18,18,0,0,0-15.63-14.59c-10.28-1.4-19.14,3.57-26.76,10-16.18,13.66-29.34,30.65-44.7,45.2a359.34,359.34,0,0,1-49.33,39.08A356.65,356.65,0,0,1,638.08,303c-35.77,14.83-90.88,29.56-123.22-.47-11.61-10.78-17.61-26.71-18.41-42.53-1.07-21.19,4.41-54.95,30-59.28,36.67-6.2,78.65,49.05,86.38,79.36,8.2,32.14-5.44,70.78-35.75,84.26-28.8,12.81-63.93,0-85.8-22.72-23.52-24.41-18.59-55.9-36.07-82.56-16-24.39-41.3-23.5-66.77-24.62" > </path> </g> </g> </svg>
Svg shows different on Firefox and Edge
I'm having some trouble with a svg image that has a number in the middle. It shows correct when using Chrome and other browsers but in Firefox and Edge the number gets wrong position. Link Here is my code. #maindiv { position: relative; width: 50px; height: 50px; } .number { font-family: initial; font-size: 2.5em; font-weight: 700; text-align: center; } <div id="maindiv" class="" style=""> <svg viewBox="0 -10 50 90" enable-background="new 0 0 50 50"> <defs> <!-- Background image for the svg --> <pattern id="image_594121ec06330" patternUnits="userSpaceOnUse" height="50" width="50" x="0" y="20"> <image x="0" y="0" height="50" width="50" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://via.placeholder.com/50x50"> </image> </pattern> <!-- two colors for the number --> <linearGradient id="textcolor_594121ec06343" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="50%" stop-color="#ff0100"></stop> <stop offset="50%" stop-color="#0600c4"></stop> <stop offset="50%" stop-color="#0600c4"></stop> <stop offset="0" stop-color="#0600c4"></stop> </linearGradient> </defs> <rect class="cellImage" id="top" x="0" y="20" width="50" height="50" style="" fill="url(#image_594121ec06330)"></rect> <text class="number " x="50%" y="55%" alignment-baseline="middle" text-anchor="middle" fill="url(#textcolor_594121ec06343)">0</text> </svg> And here is the same code on jsfiddle https://jsfiddle.net/41s39p63/ I know this can be fixed by making some if-conditions that changes some svg attributes to place the number in the middle, if the user is on Firefox or Edge but I prefer not to use that solution. Is there anyone out there who can help me with a solution to this issue so it works on all browsers?
Firefox does not support alignment-baseline. You should be able to use dominant-baseline instead to get the same effect.
Apply CSS on part of line element in SVG [duplicate]
This question already has an answer here: line segmentation in D3.js (1 answer) Closed 6 years ago. I am creating several horizontal and vertical lines and I want to paint a segment of the line say from point a to point b in some other color. I can to the same creting multiple lines but can it be done using some svg or d3 library where you can keep the same line and just paint a segment part of that line in different css?
You can use a gradient for the stroke <!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Gradients --> <svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="Gradient1"> <stop class="stop1" offset="0%" /> <stop class="stop2" offset="50%" /> <stop class="stop3" offset="100%" /> </linearGradient> <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"> <stop offset="0%" stop-color="red" /> <stop offset="50%" stop-color="black" stop-opacity="0" /> <stop offset="100%" stop-color="blue" /> </linearGradient> <style type="text/css"> <![CDATA[ #rect1 { fill: url(#Gradient1); } .stop1 { stop-color: red; } .stop2 { stop-color: black; stop-opacity: 0; } .stop3 { stop-color: blue; } ]]> </style> </defs> <line x1="20" y1="100" x2="100" y2="20" stroke="url(#Gradient2)" /> <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)" /> </svg>
Laggy animation on Firefox
I've replicated this effect using mask and filter. This is what I've done: Applied two masks on two different text elements, one on the left for the blurred text and one on the right for the normal text. Animated both masks and the ellipse to get the final effect. Everything works fine, however the animation is lagging on Firefox. Is there any way to make the animation smooth? CodePen body, html { height: 100%; margin: 0; background: -webkit-radial-gradient(center, ellipse, #300 10%, #000 100%); background: -moz-radial-gradient(center, ellipse, #300 10%, #000 100%); background: radial-gradient(center, ellipse, #300 10%, #000 100%); } svg { position: relative; width: 100%; left: 50%; top: 50%; transform: translate(-50%, -50%); } <svg width="100%" height="200" viewBox="0 0 700 200"> <defs> <filter id="blur"> <feGaussianBlur in="SourceGraphic" stdDeviation="3" /> </filter> <mask id="mask-left" maskUnits="userSpaceOnUse" x="0" y="0" width="700" height="200"> <path id="d1" d="M0,30 h0 c-35,15 -35,125 0,140 h0z" fill="white" /> <animate xlink:href="#d1" attributeType="XML" attributeName="d" from="M0,30 h0 c-35,15 -35,125 0,140 h-0z" to="M0,30 h700 c-35,15 -35,125 0,140 h-700z" dur="10s" repeatCount="indefinite" /> </mask> <mask id="mask-right" maskUnits="userSpaceOnUse" x="0" y="0" width="700" height="200"> <path id="d2" d="M700,30 h-672 c-35,15 -35,125 0,140 h672z" fill="white" /> <animate xlink:href="#d2" attributeType="XML" attributeName="d" from="M700,30 h-700 c-35,15 -35,125 0,140 h700z" to="M700,30 h0 c-35,15 -35,125 0,140 h0z" dur="10s" repeatCount="indefinite" /> </mask> </defs> <text mask="url(#mask-right)" x="350" y="120" fill="white" text-anchor="middle" font-size="50" font-family="Ubuntu">Magic of Filter and Masking</text> <text mask="url(#mask-left)" filter="url(#blur)" x="350" y="120" fill="white" text-anchor="middle" font-size="50" font-family="Ubuntu">Magic of Filter and Masking</text> <ellipse id="e" cx="26" cy="100" rx="25" ry="70" fill="none" stroke="#600" stroke-width="2" /> <animate xlink:href="#e" attributeType="XML" attributeName="cx" from="0" to="700" dur="10s" repeatCount="indefinite" /> </svg>
I have taken a look at your svg animation in different browsers. But it works without any lagging in FireFox and Chrome, but in Internet Explorer it's not working at all. Maybe make use of Fakesmile, this is supported for Internet Explorer.
problems with 'mask' in firefox
I'm at the end of my rope here. This 'mask' should work right? Well, I'm beginning to doubt. My example is at http://50.63.191.172/mask.html. I really don't know what else I could try. I do have some constraints: I would like to have the svg external to any html page / css stylesheet because it will be used from multiple places. I would like to have svg non size predetermined, because I don't want to have multiple versions for various sizes; there should be only one, so that it can be cached by browsers. I can't have the image specified inside the svg. The svg is a styling to be applied to any potential image. I've tried multiple ways to make this work but no luck so far. It works just fine in Chrome/Safari using their '-webkit-mask' property. I've had "some" success with firefox and 'mask' if I specify the width and height of the masking rect in absolute pixels, but not as 100%. Is what I want even doable (an auto-scaling mask in firefox)? If yes, what am I missing? The frustrating part, sometimes if I keep reloading the page, the images appear unmasked, only to be wiped off immediately after finish displaying. Here's my svg: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <mask id="c1"> <g id="group"> <linearGradient id="g" gradientUnits="objectBoundingBox" x2="0" y2="1"> <stop stop-color="white" offset="0"/> <stop stop-color="white" stop-opacity="0" offset="1"/> </linearGradient> <rect x="0" y="0" width="100%" height="100%" fill="url(#g)" /> </g> </mask> </defs> <use xlink:href="#group"/> </svg> And this is my html/css combined: <html lang="en"> <head> <meta charset=utf-8> <title>Testing mask in various browsers</title> <style> .masked { mask: url(mask.svg#c1); /*Firefox */ -webkit-mask: url('mask.svg'); /*Chrome, Safari */ } .nob { border: none; outline: none; } div.stage { position: relative; } .inline { display: inline-block; } span.stage { background-repeat: no-repeat; background-position: center; display: inline-block; position: absolute; left: 0px; top: 0px; } .big { width:600px; height:588px; } .normal { width:300px; height:294px; } .small { width:150px; height:147px; } </style> </head> <body style="background-image: url(background.gif);"> <div class="stage inline big"> <a class="nob" href="mask.html"><img class="nob masked" src="b_pic.jpg"/></a> </div> <div class="stage inline normal"> <a class="nob" href="mask.html"><img class="nob masked" src="pic.jpg"/></a> </div> <div class="stage inline small"> <a class="nob" href="mask.html"><img class="nob masked" src="s_pic.jpg"/></a> </div> </body> </html> What am I missing?
Turns out FF doesn't do percent. Instead it likes to work in objectBoundingBox units between 0 and 1. Well, Chrome/Safari don't like that. But there is a way to split the difference. Here's my working current version which I will aim to optimize next. <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <mask id="c1" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox"> <g id="group1"> <linearGradient id="g1" gradientUnits="objectBoundingBox" x2="0" y2="1"> <stop stop-color="white" offset="0"/> <stop stop-color="white" stop-opacity="0" offset="1"/> </linearGradient> <rect x="0" y="0" width="1" height="1" fill="url(#g1)" /> </g> </mask> <mask id="c2"> <g id="group2"> <linearGradient id="g2" gradientUnits="objectBoundingBox" x2="0" y2="1"> <stop stop-color="white" offset="0"/> <stop stop-color="white" stop-opacity="0" offset="1"/> </linearGradient> <rect x="0" y="0" width="100%" height="100%" fill="url(#g2)" /> </g> </mask> </defs> <use xlink:href="#group2"/> </svg> So it goes, it can be done.