Outlined triangle svg animation - css

I've created a simple outlined triangle. The problem i need to solve - is to create animation of filling the gap between triangles from bottom to top.
When i am using the fill option for polygons, the fill area overlaps the other triangle, so that there is no "hole" in the shape.
body{
background: #7085EA;
}
.triangle-container{
width: 500px;
margin: auto;
text-align:center;
}
.triangle {
stroke: #fff;
fill: transparent;
}
<div class="triangle-container">
<svg height="500" width="500">
<polygon points="250,100 100,400 400,400" class="triangle"/>
<polygon points="250,180 160,360 340,360" class="triangle"/>
</svg>
</div>
Initial codepen is here.
The area that needs to be filled is shown on screenshot here
Any help is appreciated. Thanks in advance!

Based on the advices here, and an another SO issue, came up with the following solution:
body{
background: #7085EA;
}
.triangle-container{
width: 500px;
margin: auto;
text-align:center;
}
.triangle {
stroke: #fff;
}
<div class="triangle-container">
<svg height="500" width="500">
<linearGradient id="loading" x1="0.5" y1="1" x2="0.5" y2="0">
<stop offset="40%" stop-opacity="1" stop-color="#fff">
<animate attributeName="offset" values="0;1;0" repeatCount="indefinite" dur="10s" begin="0s"/>
</stop>
<stop offset="40%" stop-opacity="0" stop-color="#fff">
<animate attributeName="offset" values="0;1;0" repeatCount="indefinite" dur="10s" begin="0s"/>
</stop>
</linearGradient>
<path d="M250,100 L100,400 400,400 250,100 M250,180 L340,360 160,360 250,180z" class="triangle" fill="url(#loading)"></path>
</svg>
</div>

Related

SVG background applied to SVG shape stroke repeats instead of spreading

Let's say, I have a simple SVG: 1 circle, 1 linear gradient, apllied to its stroke.
I want gradient to spread along the stroke according to the stop-points: start from blue on the one end and finish on yellow color on another end.
But it somehow mirrors and repeats: blue color is in the middle and yellow on both ends of the circle.
What should I do to avoid repeating?
div {
width: 200px;
height: 200px;
}
svg {
width: 100%;
height: 100%;
}
<div>
<svg viewport="0 0 100 100" version="1.1">
<defs>
<linearGradient id="b7781eda-4425-42b1-a879-c912f4606b76">
<stop stop-color="#4158D0" offset="0%"></stop>
<stop stop-color="#C850C0" offset="46%"></stop>
<stop stop-color="#FFCC70" offset="100%"></stop>
</linearGradient>
</defs>
<circle r="92.5" cx="100" cy="100" fill="transparent" stroke="url(#b7781eda-4425-42b1-a879-c912f4606b76)" stroke-linecap="round" stroke-width="15" stroke-dasharray="581.1946409141117" stroke-dashoffset="58.119464091411174"></circle>
</svg>
</svg>
</div>

How to crop an image width svg?

How to crop an image with path in this svg?
<svg width="1440" height="568" viewBox="0 0 1440 568" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0H1440V481.821L720 568L0 481.821V0Z" fill="url(#paint0_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="720" y1="607.026" x2="720" y2="35.2649" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0"/>
<stop offset="1" stop-color="#0997FF" stop-opacity="0.56"/>
</linearGradient>
</defs>
</svg>
I want to set linearGradient of svg on an image and extra space in bottom of image be as same as background color of body(navy blue):
<div class="bg"></div>
.bg {
width: 100vw;
min-height: 500px;
background: url("../assets/images/mySvg.svg"),
url("../assets/images/myImage.jpg");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
What I have:
What I want:
Put the image into the SVG.
Combine the image and the gradient into an SVG group (<g>)
Then clip that group with an SVG <clipPath> defined using your original path.
Put the SVG inside the <div>
body {
background-color: linen;
}
.bg {
width: 100vw;
min-height: 500px;
}
<div class="bg">
<svg width="100%" viewBox="0 0 1440 568">
<defs>
<clipPath id="clip">
<path d="M0 0H1440V481.821L720 568L0 481.821V0Z"/>
</clipPath>
<linearGradient id="paint0_linear" x1="720" y1="607.026" x2="720" y2="35.2649" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0"/>
<stop offset="1" stop-color="#0997FF" stop-opacity="0.56"/>
</linearGradient>
</defs>
<g clip-path="url(#clip)">
<image xlink:href="http://placekitten.com/1440/568" width="1440" height="568"/>
<rect width="1440" height="568" fill="url(#paint0_linear)"/>
</g>
</svg>
<p>More content here.</p>
</div>

How to set the size of the handle in a QSlider?

I'm trying to add some style to a QSlider I want to use a custom image as the handle that the user drags back and forth. While I've figured out how to use style sheets to have a custom icon drawn where the handle should be, the image is being drawn much too small and I cannot figure out how to make it larger.
Setting width and height seem to do nothing. I've tried using image, border-image and background-image, but none give me the ability to set the size of the handle image. Does anyone know how to do this?
This is the style sheet that I've been adding to my QSlider in QtDesigner:
QSlider::handle:vertical {
image: url(:/data/icons/mixer-slider-handle.svg);
width:64px;
height:64px;
}
This is the SVG:
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="30"
height="45"
viewBox="0 0 7.9374997 11.90625"
version="1.1"
id="svg8"
>
<defs
id="defs2">
<linearGradient
id="linearGradient844"
inkscape:collect="always">
<stop
id="stop840"
offset="0"
style="stop-color:#cecece;stop-opacity:1;" />
<stop
id="stop842"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient824">
<stop
style="stop-color:#cecece;stop-opacity:1;"
offset="0"
id="stop820" />
<stop
style="stop-color:#ffffff;stop-opacity:1"
offset="1"
id="stop822" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient824"
id="linearGradient826"
x1="-3.9103179"
y1="297.24557"
x2="-3.8304768"
y2="285.38882"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8683302,0,0,0.96503255,7.3827223,9.9179025)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient844"
id="linearGradient838"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.86322913,0,0,0.81935486,7.5301966,52.317886)"
x1="-3.8119318"
y1="285.99686"
x2="-3.7885454"
y2="296.82458" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-285.09375)">
<rect
style="fill:url(#linearGradient826);fill-opacity:1;stroke:#0e0e0e;stroke-width:0.1373108;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect818"
width="5.157938"
height="11.397007"
x="1.453124"
y="285.36124"
ry="2.866178" />
<rect
style="opacity:1;fill:url(#linearGradient838);fill-opacity:1;stroke:none;stroke-width:0.12615089;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect828"
width="4.6027613"
height="8.9100981"
x="1.7161824"
y="286.60291"
ry="2.184411" />
<path
style="fill:none;stroke:#000000;stroke-width:0.24780074px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.8804469,291.0695 4.3266789,0.047"
id="path846"
inkscape:connector-curvature="0" />
</g>
</svg>
Looks like the answer is to set the margin attribute for both the groove and the handle to reflect the size of the handle you are using.
This worked for me:
.QSlider::groove:vertical {
border: 1px solid #111;
background-color: #333;
width: 6px;
margin: 24px 12px;
}
.QSlider::handle:vertical {
image: url(:/data/icons/mixer-slider-handle.svg);
margin: -24px -12px;
height: -30px;
}

CSS shape something like tea drop

I am trying to create this shape ( on the uploaded image ) only with css borders but I have problem with the corners they are not accepting the right shape. May I ask you guys for advice or best practice how to create it ?
Here is my code
.tea-drop {
width: 90px;
height: 25px;
display: block;
background: #000;
border-top-left-radius: 100%;
border-top-right-radius: 60%;
border-bottom-left-radius: 70%;
border-bottom-right-radius: 67%;
}
<div class="tea-drop"></div>
SVG is the recommended way to create such shapes. It offers simplicity and scale-ability.
We can use SVG's path element to create a shape like above and fill it with some solid color, gradient or a pattern.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Following code will create above shape:
<path d="M 0,0
C 100,10 120,150 60,75
Z" />
Below is a brief description of path commands used in above code:
M command is used to define the starting point. It appears at the beginning and specify the point from where drawing should start.
Q command is used to draw curves.
Z command is used to close current path. It draws a straight line from current point to the starting point to close the shape.
Output Image:
Working Example:
* {box-sizing: border-box;}
body {
background: linear-gradient(teal, skyblue);
text-align: center;
min-height: 100vh;
padding: 10px;
margin: 0;
}
<svg width="200" height="200" viewBox="0 0 100 100">
<path d="M0,0
C 100,10 120,150 60,75
Z" />
</svg>
This shape can be filled with gradient or pattern as well. <linearGradient> element is used to define a gradient in SVG. This element can then be referenced later using an id attribute to fill or outline any shape.
<linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="orange" />
<stop offset="1" stop-color="green" />
</linearGradient>
The direction of the gradient is controlled by the x1, y1, x2 and y2 while <stop> elements are used to define colors and their position along the gradient line.
Output Image:
Working Example:
* {box-sizing: border-box;}
body {
background: linear-gradient(teal, skyblue);
text-align: center;
min-height: 100vh;
padding: 10px;
margin: 0;
}
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="orange" />
<stop offset="1" stop-color="green" />
</linearGradient>
</defs>
<path d="M0,0
C 100,10 120,150 60,75
Z" fill="url('#grad')" />
</svg>
We can even apply shadow to this shape using SVG's filters. This article on MDN explains the basics of filters.
Output Image:
Working Example:
* {box-sizing: border-box;}
body {
background: linear-gradient(teal, skyblue);
text-align: center;
min-height: 100vh;
padding: 10px;
margin: 0;
}
<svg width="240" height="240" viewBox="0 0 120 120">
<defs>
<linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="orange" />
<stop offset="1" stop-color="green" />
</linearGradient>
<filter id="shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" />
<feMerge>
<feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<path d="M10,10
C 110,20 130,160 70,85
Z" fill="url('#grad')" filter="url('#shadow')" />
</svg>
Useful Resources:
Below are some useful links for SVG:
Specification
MDN
You can use CSS3 to make that.
.tear {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
width: 10em;
height: 10em;
border: none;
-webkit-border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
font: normal 100%/normal Arial, Helvetica, sans-serif;
color: rgba(0,0,0,1);
-o-text-overflow: clip;
text-overflow: clip;
background: rgb(0,0,0);
-webkit-transform: rotateX(42.5447924299deg) rotateY(100deg) rotateZ(-45.26deg) translateY(1px) ;
transform: rotateX(42.5447924299deg) rotateY(100deg) rotateZ(-45.26deg) translateY(1px) ;
-webkit-transform-origin: 50% 0 0;
transform-origin: 50% 0 0;
}
<div class="tear"></div>
Reference: http://enjoycss.com/SfB
I saved the link, you can customized it for yourself.

SVG working on html image tag -- not on HTML5 canvas

I have a problem here. I need something to be implemented onclick of a button. I searched on the net and found out that SVG was an easier way to do it rather than CSS stylesheets.
I have an HTML5 canvas (which is basically a snapshot from a video stream that I have taken and drawn on to the HTML 5 canvas using drawImage()). On click of a button, I want the image with the following effect to come on the canvas instead of the original image.
My problem is that I am able to replicate the effect if I apply the effect on just an image. However, on the canvas it gives me the mask separately and the image separately. This is the code that I am using for the SVG
<svg height="0">
<defs>
<mask id="mask-radial">
<rect width="500" height="500" fill="url(#g1)"></rect>
<radialGradient id="g1" cx="80%" cy="80%" r="100%">
<stop stop-color="black" offset="50%"/>
<stop stop-color="white" offset="110%"/>
</radialGradient>
</mask>
<!--<mask id="mask-linear">
<rect width="400" height="300" fill="url(#l1)"></rect>
<linearGradient id="l1" x1="0" y1="0" x2="0" y2="1">
<stop stop-color="white" offset="0%"/>
<stop stop-color="black" offset="30%"/>
<stop stop-color="white" offset="100%"/>
</linearGradient>
</mask> -->
<filter id="filtre1">
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
</filter>
<!-- <filter id="filtre2">
<feGaussianBlur in="SourceGraphic" stdDeviation="10"/>
</filter> -->
</defs>
</svg>
This is how I am calling it in CSS
.effet{
width: 500px; height: 500px;
margin: 0 auto 50px auto;
box-shadow: 0 1px 5px rgba(0,0,0,.5);
}
.effet img{
position: absolute;
}
.filtre--r{
-webkit-mask: -webkit-radial-gradient( center, closest-side, transparent 50%, black 80%);
-webkit-mask: radial-gradient( closest-side at center, transparent 50%, black 80%);
-webkit-filter: blur(40px);
mask: url('#mask-radial');
filter: url('#filtre1');
}
and these are my HTML elements.
<div class="effet">
<img src="/static/images/noEffect.png" alt="" />
<img class="filtre filtre--r" src="/static/images/noEffect.png" alt="" />
</div>
Can somebody please tell me how I can recreate the effect for my canvas? Thanks in advance.
I researched and found that HTML5 Canvas radial gradient was an effective solution.
var lightSize = 100;
var x = 200;
var y = 200;
var radialGradient = context.createRadialGradient(x, y, 0,x, y, lightSize);
radialGradient.addColorStop(0, "#FFFF99"); // color at start circle
radialGradient.addColorStop(0.9, "#FFFF99"); //color at offset 0.9
radialGradient.addColorStop(1, '#7D7D5C');// color of finish circle
context.globalCompositeOperation = "multiply";
context.fillStyle = radialGradient;
Was able to recreate the effect totally.

Resources