Positioning many groups in SVG - css

I am trying to position a scale with numbers and lines on the top of my black half-circle gauge. The problem is that I have two groups of elements that do not fit with each other in the same group .. Thus the local coordinate system of the scale element is located on the bottom and I cannot use transform functions to place it in the center..
var r = 400;
var circles = document.querySelectorAll('.circle');
var total_circles = circles.length;
for (var i = 0; i < total_circles; i++) {
circles[i].setAttribute('r', r);
}
var meter_dimension = (r * 2) + 100;
var wrapper = document.querySelector('#wrapper');
wrapper.style.width = meter_dimension + 'px';
wrapper.style.height = meter_dimension + 'px';
var cf = 2 * Math.PI * r;
var semi_cf = cf / 2;
var z = 40 * Math.PI;
document.querySelector('#outline_ends')
.setAttribute('stroke-dasharray', 2 + ',' + (semi_cf - 2)); -
document.querySelector('#mask')
.setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#low')
.setAttribute('stroke-dasharray', semi_cf - z + ',' + cf);
for (i = 0; i <= 180; i = i + 10) {
var new_tick = noon.cloneNode(true);
new_tick.getElementsByTagName('text')[0].textContent = i;
new_tick.removeAttribute("id");
new_tick.setAttribute("transform", "rotate(" + i + " 0 0)");
gauge.appendChild(new_tick);
}
body {
background-color: grey;
}
#wrapper {
position: relative;
margin: auto;
}
#meter {
width: 100%;
height: 100%;
transform: rotateX(180deg);
}
.circle {
fill: none;
}
#mask {
stroke: yellow;
stroke-width: 60;
}
.black {
fill: none;
stroke: #000000;
stroke-width: 30;
}
.range {
stroke-width: 60;
}
.scale {
stroke: #ffffff;
}
rect {
fill: transparent;
}
<div id="wrapper">
<svg id="meter">
<g class="scale">
<circle id="mask" class="circle" cx="50%" cy="50%">
</circle>
<circle id="low" class="black" cx="50%" cy="50%" r="360">
</circle>
<circle id="outline_ends" class="circle outline" cx="50%" cy="50%">
</circle>
<g id="gauge" transform="rotate(-90)">
<g id="noon">
<rect x="-10" y="-220" width="20" height="100" />
<line x1="0" y1="-190" x2="0" y2="-180" />
<text x="0" y="-200"></text>
</g>
</g>
</g>
</svg>
</div>

This is an example of positioning a group in SVG:
You put the group in the <defs> and you reuse it with <use>. The <use> element may have a x and a y attributes that are defining the new position.
svg{border:1px solid; max-height:100vh;}
<svg viewBox="0 0 200 75">
<defs>
<g id="g1">
<rect width="20" height="20" />"
</g>
</defs>
<use xlink:href ="#g1" x="100" y="50"/>
<use xlink:href ="#g1" x="50" y="10" fill="red"/>
</svg>
In the example above I draw the same group twice, every time in a different position.

Related

How do I target each circle within svg using css?

I have this
<svg class="wheel" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" transform="scale(1.022,1.022)" viewBox="0 0 1024 1024" height="100%" width="100%">
<circle fill="#ffffff" cx="512" cy="512" r="110"></circle>
<circle stroke="#ffffff" r="456" fill="transparent" stroke-width="33" cx="512" cy="512"></circle>
</svg>
How can I style each circle using css? Thank you.
If you know that the SVG markup won't change, then this will suffice:
.wheel * {
// CSS here
}
Otherwise, give the circles a class and write like:
.wheel .wheel-circle {
// CSS here
}
If you mean each circle needs different styles then simply:
.wheel #wheel-circle-1 {
// CSS here
}
.wheel #wheel-circle-2 {
// CSS here
}
Method 1:
The best way would be to add an id to each circle:
<svg class="wheel" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" transform="scale(1.022,1.022)" viewBox="0 0 1024 1024" height="100%" width="100%">
<circle id="innerCircle" fill="#ffffff" cx="512" cy="512" r="110"></circle>
<circle id="outerCircle" stroke="#ffffff" r="456" fill="transparent" stroke-width="33" cx="512" cy="512"></circle>
</svg>
And then just target that.
#innerCircle {
fill: red;
}
#outerCircle {
stroke: blue;
}
Method 2:
But if this is not desirable, try using the nth-child selector on the parent:
.wheel:nth-child(1) {
fill: red;
}
.wheel:nth-child(2) {
stroke: blue;
}
I hope this helps!

How to wrap SVG content?

I want to use SVG in my WordPress site. The content of this SVG will be changed and I want it to be dynamic:
Here is my code:
<div style="height:60px;" class="gmr_main_page_svg_div">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="6773 1755 730 81" style="height:60px;" class="gmr_main_page_svg">
<defs>
<style>
.cls-1 {
clip-path: url(#clip-iPhone_6_7_8_1);
}
.cls-2 {
fill: #0652fd;
}
.cls-3, .cls-4 {
fill: none;
stroke: #0652fd;
}
.cls-3 {
stroke-width: 3px;
}
.cls-4 {
stroke-width: 4px;
}
.cls-5 {
fill: #fff;
font-size: 25px;
font-family: IRANSans-Bold, IRANSans;
font-weight: 700;
}
.cls-6 {
fill: rgba(255,255,255,0);
}
</style>
<clipPath id="clip-iPhone_6_7_8_1">
<rect x="6773" y="1755" width="900" height="81"/>
</clipPath>
</defs>
<g id="iPhone_6_7_8_1" data-name="iPhone 6/7/8 – 1" class="cls-1">
<rect class="cls-6" x="6773" y="1755" width="730" height="81"/>
<g id="Group_2830" data-name="Group 2830" transform="translate(6586 1751)">
<path id="Path_3672" data-name="Path 3672" class="cls-2" d="M1319.065,1810h189.586v-69.9h-131.61Z" transform="translate(-593 -1732)"/>
<path id="Path_3673" data-name="Path 3673" class="cls-3" d="M1319.065,1810h189.586v-69.9h-131.61Z" transform="translate(-600 -1736)"/>
<line id="Line_108" data-name="Line 108" class="cls-4" x1="728" transform="translate(187.5 76.5)"/>
</g>
<text id="خدمات_ما" data-name="خدمات ما" class="cls-5" transform="translate(7376 1779)"><tspan x="130.443" y="22">ویژگی‌های طراحی لوگو</tspan></text>
</g>
</svg>
</div>
Here is my a fiddle.
I used some image to SVG converters and this is the output of my image.
You can put the code on functions.php file,
Please check below code -
function cc_mime_types($mimes) {
$mimes['svg'] = 'image/svg+xml';
return $mimes;
}
add_filter('upload_mimes', 'cc_mime_types');
Try it!!

Animate dashed SVG line

I would like to animate a dashed line in a SVG-file. The line should »grow« from 0 length to full length. All the methods I found are not suitable for me.
Does anyone have an idea, how to solve this?
That's the path in my svg file:
<path class="path" fill="none" stroke="#FFFFFF" stroke-miterlimit="10" d="M234.3,119
c-31-0.7-95,9-128.7,50.8"/>
To animate the line as straight line i did:
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
Of course, this is not working, when I want the line to be dashed.
Is there anybody who has an idea how to solve this?
That's my codepen: http://codepen.io/anon/pen/WpZNJY
PS: I can't use two paths over each other to hide the path underneath because I'm having a coloured background.
You can also do this just using masks as so:
.paths {
fill: none;
stroke: black;
stroke-dasharray: 5;
}
.mask {
fill: none;
stroke: white;
stroke-width: 10;
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear forwards;
}
#keyframes dash {
to {
stroke-dashoffset: 0;
}
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 830 500" >
<defs>
<path id="first" d="M234.3,119c-31-0.7-95,9-128.7,50.8"/>
<path id="vienna" d="M382.8,243.8c2.9-36.1,15.8-110.3,110.1-145.4"/>
<path id="budapest" d="M550.6,319.4c34-2.7,109-2.1,174.8,50.5"/>
<path id="salzburg" d="M265,323c21.5,12.1,57.2,39.5,60.7,85.1"/>
<path id="tyrol" d="M147.8,319.5c-27.1,7-79.7,31.3-92.8,74.2"/>
<mask id="first-mask"><use class="mask" xlink:href="#first" /></mask>
<mask id="vienna-mask"><use class="mask" xlink:href="#vienna" /></mask>
<mask id="budapest-mask"><use class="mask" xlink:href="#budapest" /></mask>
<mask id="salzburg-mask"><use class="mask" xlink:href="#salzburg" /></mask>
<mask id="tyrol-mask"><use class="mask" xlink:href="#tyrol" /></mask>
</defs>
<g class="paths">
<use xlink:href="#first" mask="url(#first-mask)" />
<use xlink:href="#vienna" mask="url(#vienna-mask)" />
<use xlink:href="#budapest" mask="url(#budapest-mask)" />
<use xlink:href="#salzburg" mask="url(#salzburg-mask)" />
<use xlink:href="#tyrol" mask="url(#tyrol-mask)" />
</g>
</svg>
This is also available as:
codepen of single dotted path
codepen of these plane tracks
Enjoy!
But note ... make sure you test your code cross-browser and fall back to animate tags or javascript if you have issues.
One of the ways to do this is with Javascript. It duplicates a path by creating a polyline.
Try the example below:
<!DOCTYPE HTML>
<html>
<head>
<style>
polyline{
stroke-dasharray:8;
stroke:black;
fill:none;
stroke-width:1;
}
</style>
</head>
<body >
This builds a smooth/dashed polylines that replicates your paths.<br>
<button onClick=animateDashPaths()>Animate Paths</button><br>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 830 500" enable-background="new 0 0 830 500" xml:space="preserve">
<path class="path" fill="none" stroke="#000000" stroke-miterlimit="10" d="M234.3,119
c-31-0.7-95,9-128.7,50.8"/>
<!-- Vienna Dash -->
<path id="pathVienna" display="none" stroke-miterlimit="10" d="M382.8,243.8
c2.9-36.1,15.8-110.3,110.1-145.4"/>
<!-- Budapest Dash -->
<path id="pathBudapest" display="none" stroke-miterlimit="10" d="M550.6,319.4
c34-2.7,109-2.1,174.8,50.5"/>
<!-- Salzburg Dash -->
<path id="pathSalzburg" display="none" stroke-miterlimit="10" d="M265,323
c21.5,12.1,57.2,39.5,60.7,85.1"/>
<!-- Tyrol Dash -->
<path id="pathTyrol" display="none" stroke-miterlimit="10" d="M147.8,319.5
c-27.1,7-79.7,31.3-92.8,74.2"/>
</svg>
<script>
//---button---
function animateDashPaths()
{
var NS="http://www.w3.org/2000/svg"
//----Vienna----------------
var endLengthVienna=pathVienna.getTotalLength()
var lengthDeltaVienna=endLengthVienna/200
var polylineVienna=document.createElementNS(NS,"polyline")
Layer_1.appendChild(polylineVienna)
var pntListVienna=polylineVienna.points
var iTVienna=setInterval(drawPathVienna,5)
var cntVienna=0
function drawPathVienna()
{
var len=lengthDeltaVienna*cntVienna++
if(len<endLengthVienna)
{
var pnt=pathVienna.getPointAtLength(len)
pntListVienna.appendItem(pnt)
}
else
clearInterval(iTVienna)
}
//----Budapest----------------
var endLengthBudapest=pathBudapest.getTotalLength()
var lengthDeltaBudapest=endLengthBudapest/200
var polylineBudapest=document.createElementNS(NS,"polyline")
Layer_1.appendChild(polylineBudapest)
var pntListBudapest=polylineBudapest.points
var iTBudapest=setInterval(drawPathBudapest,5)
var cntBudapest=0
function drawPathBudapest()
{
var len=lengthDeltaBudapest*cntBudapest++
if(len<endLengthBudapest)
{
var pnt=pathBudapest.getPointAtLength(len)
pntListBudapest.appendItem(pnt)
}
else
clearInterval(iTBudapest)
}
//----Salzburg----------------
var endLengthSalzburg=pathSalzburg.getTotalLength()
var lengthDeltaSalzburg=endLengthSalzburg/200
var polylineSalzburg=document.createElementNS(NS,"polyline")
Layer_1.appendChild(polylineSalzburg)
var pntListSalzburg=polylineSalzburg.points
var iTSalzburg=setInterval(drawPathSalzburg,5)
var cntSalzburg=0
function drawPathSalzburg()
{
var len=lengthDeltaSalzburg*cntSalzburg++
if(len<endLengthSalzburg)
{
var pnt=pathSalzburg.getPointAtLength(len)
pntListSalzburg.appendItem(pnt)
}
else
clearInterval(iTSalzburg)
}
//----Tyrol----------------
var endLengthTyrol=pathTyrol.getTotalLength()
var lengthDeltaTyrol=endLengthTyrol/200
var polylineTyrol=document.createElementNS(NS,"polyline")
Layer_1.appendChild(polylineTyrol)
var pntListTyrol=polylineTyrol.points
var iTTyrol=setInterval(drawPathTyrol,5)
var cntTyrol=0
function drawPathTyrol()
{
var len=lengthDeltaTyrol*cntTyrol++
if(len<endLengthTyrol)
{
var pnt=pathTyrol.getPointAtLength(len)
pntListTyrol.appendItem(pnt)
}
else
clearInterval(iTTyrol)
}
}
</script>
</body>
</html>
I think you should just be able to add stroke-dasharray to your animation and lower the dash array in your css. An updated version of your codepen; http://codepen.io/harvey89/pen/NpaWBE
stroke-dashoffset: 1000;
stroke-dasharray: 10;
#keyframes dash {
to {
stroke-dashoffset: 0;
stroke-dasharray: 10;
}
}
You'll probably have to play around with numbers to get your desired effect though

transition not working on SVG

I am trying to animate an SVG where I want my line tags inside SVG to show smoothly when I hover over the SVG. I have applied CSS transition to it but it is not working.
here is my example:https://codepen.io/Ali_Farooq_/pen/WoaRMV?editors=1100
I'm new to animating SVGs and I think there is some sort of bug that I don't know of. Any advice or tip would be appreciated.
Here is my code
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 230.8 181.7" style="enable-background:new 0 0 230.8 181.7;">
<circle id="XMLID_1_" class="circle" cx="115.4" cy="90.9" r="86.9"/>
<rect id="XMLID_2_" x="100.6" y="20.9" class="rectangle" width="29.6" height="107.2"/>
<polygon id="XMLID_3_" class="polygon" points="136.6,128.1 115.1,165.4 93.6,128.1 "/>
<line id="XMLID_4_" class="lines line1" y1="40.6" x2="230.8" y2="40.6"/>
<line id="XMLID_5_" class="lines line2" y1="133.6" x2="230.8" y2="133.6"/>
<g id="XMLID_6_">
<path id="XMLID_10_" d="M20.5,79.7V54.1h7.2c2.2,0,4.2,0.5,5.9,1.5s3,2.4,4,4.2s1.4,3.9,1.4,6.3v1.6c0,2.4-0.5,4.5-1.4,6.3
s-2.3,3.2-4,4.2s-3.7,1.5-6,1.5H20.5z M23.9,56.9V77h3.6c2.6,0,4.6-0.8,6.1-2.4s2.2-3.9,2.2-6.9v-1.5c0-2.9-0.7-5.2-2-6.8
c-1.4-1.6-3.3-2.4-5.8-2.5H23.9z"/>
<path id="XMLID_13_" d="M63.8,67.7c0,2.5-0.4,4.7-1.3,6.6s-2,3.3-3.6,4.3s-3.4,1.5-5.4,1.5c-2,0-3.8-0.5-5.4-1.5s-2.8-2.4-3.6-4.2
s-1.3-4-1.3-6.4v-1.8c0-2.5,0.4-4.6,1.3-6.5s2.1-3.3,3.6-4.3s3.4-1.5,5.4-1.5c2.1,0,3.9,0.5,5.4,1.5s2.8,2.4,3.6,4.3
s1.3,4.1,1.3,6.6V67.7z M60.5,66.1c0-3-0.6-5.4-1.8-7s-2.9-2.4-5.1-2.4c-2.1,0-3.8,0.8-5,2.4s-1.9,3.9-1.9,6.8v1.9
c0,2.9,0.6,5.3,1.9,6.9s2.9,2.5,5.1,2.5c2.2,0,3.9-0.8,5.1-2.4s1.8-3.9,1.8-6.8V66.1z"/>
<path id="XMLID_17_" d="M74.4,71.6l0.5,3.4l0.7-3l5.1-17.9h2.8L88.5,72l0.7,3.1l0.5-3.4l4-17.5h3.4l-6.2,25.6h-3.1l-5.3-18.7
l-0.4-2l-0.4,2l-5.5,18.7h-3.1L67,54.1h3.4L74.4,71.6z"/>
<path id="XMLID_19_" d="M120.5,79.7h-3.4L104.2,60v19.7h-3.4V54.1h3.4l12.9,19.8V54.1h3.4V79.7z"/>
<path id="XMLID_21_" d="M129.9,77H142v2.8h-15.5V54.1h3.4V77z"/>
<path id="XMLID_23_" d="M164.4,67.7c0,2.5-0.4,4.7-1.3,6.6s-2,3.3-3.6,4.3s-3.4,1.5-5.4,1.5c-2,0-3.8-0.5-5.4-1.5s-2.8-2.4-3.6-4.2
s-1.3-4-1.3-6.4v-1.8c0-2.5,0.4-4.6,1.3-6.5s2.1-3.3,3.6-4.3s3.4-1.5,5.4-1.5c2.1,0,3.9,0.5,5.4,1.5s2.8,2.4,3.6,4.3
s1.3,4.1,1.3,6.6V67.7z M161,66.1c0-3-0.6-5.4-1.8-7s-2.9-2.4-5.1-2.4c-2.1,0-3.8,0.8-5,2.4s-1.9,3.9-1.9,6.8v1.9
c0,2.9,0.6,5.3,1.9,6.9s2.9,2.5,5.1,2.5c2.2,0,3.9-0.8,5.1-2.4S161,71,161,68V66.1z"/>
<path id="XMLID_26_" d="M183.2,73h-10.7l-2.4,6.7h-3.5l9.8-25.6h3l9.8,25.6h-3.5L183.2,73z M173.5,70.3h8.7l-4.4-12L173.5,70.3z"/>
<path id="XMLID_29_" d="M192.6,79.7V54.1h7.2c2.2,0,4.2,0.5,5.9,1.5s3,2.4,4,4.2s1.4,3.9,1.4,6.3v1.6c0,2.4-0.5,4.5-1.4,6.3
s-2.3,3.2-4,4.2s-3.7,1.5-6,1.5H192.6z M196,56.9V77h3.6c2.6,0,4.6-0.8,6.1-2.4s2.2-3.9,2.2-6.9v-1.5c0-2.9-0.7-5.2-2-6.8
c-1.4-1.6-3.3-2.4-5.8-2.5H196z"/>
</g>
<g id="XMLID_8_">
<path id="XMLID_36_" d="M88.2,107.9h-5.8V118h-3.3V93.1h8.2c2.8,0,5,0.6,6.5,1.9c1.5,1.3,2.3,3.1,2.3,5.6c0,1.5-0.4,2.9-1.3,4
c-0.8,1.2-2,2-3.5,2.6l5.8,10.6v0.2h-3.5L88.2,107.9z M82.4,105.2h5c1.6,0,2.9-0.4,3.9-1.3c1-0.8,1.4-2,1.4-3.4
c0-1.5-0.5-2.7-1.4-3.5s-2.2-1.2-4-1.3h-5V105.2z"/>
<path id="XMLID_39_" d="M114.7,106.5h-10.8v8.8h12.5v2.7h-15.8V93.1h15.6v2.7h-12.4v8h10.8V106.5z"/>
<path id="XMLID_41_" d="M127.8,106.9c-2.8-0.8-4.9-1.8-6.1-3c-1.3-1.2-1.9-2.6-1.9-4.4c0-2,0.8-3.6,2.3-4.9
c1.6-1.3,3.6-1.9,6.1-1.9c1.7,0,3.2,0.3,4.6,1c1.3,0.7,2.4,1.6,3.1,2.7c0.7,1.2,1.1,2.4,1.1,3.8h-3.3c0-1.5-0.5-2.7-1.4-3.6
s-2.3-1.3-4-1.3c-1.6,0-2.9,0.4-3.8,1.1c-0.9,0.7-1.4,1.7-1.4,3c0,1,0.4,1.9,1.3,2.6c0.9,0.7,2.3,1.3,4.4,1.9
c2.1,0.6,3.7,1.2,4.9,1.9c1.2,0.7,2,1.5,2.6,2.5c0.6,0.9,0.8,2,0.8,3.3c0,2-0.8,3.6-2.4,4.8c-1.6,1.2-3.7,1.8-6.3,1.8
c-1.7,0-3.3-0.3-4.8-1c-1.5-0.7-2.6-1.6-3.4-2.7c-0.8-1.1-1.2-2.4-1.2-3.9h3.3c0,1.5,0.6,2.7,1.7,3.6c1.1,0.9,2.6,1.3,4.5,1.3
c1.7,0,3.1-0.4,4-1.1c0.9-0.7,1.4-1.7,1.4-2.9c0-1.2-0.4-2.2-1.3-2.8S130.1,107.5,127.8,106.9z"/>
<path id="XMLID_43_" d="M158.8,93.1V110c0,2.3-0.7,4.3-2.2,5.8c-1.5,1.5-3.5,2.3-6,2.5l-0.9,0c-2.7,0-4.9-0.7-6.5-2.2
c-1.6-1.5-2.4-3.5-2.5-6.1v-17h3.2v16.9c0,1.8,0.5,3.2,1.5,4.2c1,1,2.4,1.5,4.2,1.5c1.9,0,3.3-0.5,4.3-1.5c1-1,1.5-2.4,1.5-4.2
V93.1H158.8z"/>
<path id="XMLID_45_" d="M168.2,93.1l8.1,20.3l8.1-20.3h4.3V118h-3.3v-9.7l0.3-10.5l-8.2,20.1h-2.5l-8.2-20.1l0.3,10.4v9.7H164V93.1
H168.2z"/>
<path id="XMLID_47_" d="M208.6,106.5h-10.8v8.8h12.5v2.7h-15.8V93.1h15.6v2.7h-12.4v8h10.8V106.5z"/>
</g>
<g id="XMLID_7_">
<path id="XMLID_32_" d="M24.9,93.2l8.1,20.3l8.1-20.3h4.3V118h-3.3v-9.7l0.3-10.5L34.3,118h-2.5l-8.2-20.1l0.3,10.4v9.7h-3.3V93.2
H24.9z"/>
<path id="XMLID_34_" d="M58.4,105.7l6.5-12.5h3.7L60,108.8v9.3h-3.3v-9.3l-8.6-15.6h3.8L58.4,105.7z"/>
</g>
</svg>
and my CSS
.circle {
fill: none;
stroke: #767270;
stroke-width: 8;
stroke-miterlimit: 10;
}
.rectangle {
fill: #767270;
stroke: #767270;
stroke-width: 5;
stroke-miterlimit: 10;
}
.polygon {
fill: #767270;
stroke: #767270;
stroke-width: 5;
stroke-miterlimit: 10;
}
.lines{
fill: none;
stroke: #46677f;
stroke-width: 3;
stroke-miterlimit: 10;
stroke-dasharray: 235;
stroke-dashoffset: 235;
tranistion: stroke-dashoffset 5s linear;
}
svg:hover .lines {
stroke-dashoffset: 0;
}
#XMLID_6_ {
fill: #46677f;
}
#XMLID_8_ {
fill: #46677f;
}
#XMLID_7_ {
fill: #46677f;
}
#keyframes linesGrowth {
from {
stroke-dashoffset: -235;
} to {
stroke-dashoffset: 0;
}
}

How to generate a elongated hexagon shape with two circular sides?

I'm trying to generate this sort of shape within my design:
In which a canvas element appears in the middle part of the circle, and this kind of elongated hexagon appears around the outside.
However, I am having some issues with the shape - primarily how I would make the shape with a gradient or background image as well (i.e. the internal puzzle piece looking bit will be an image). The outer background will be a solid background colour (#222).
Current Attempt
My current attempt is using a background gradient to generate most of the shape, and using pseudo elements for the two circlular parts either side::
var a = 100; // size of the black hole.
var b = 200; // distance of black hole from canvas center.
var c = 1; // speed of black hole rotation.
var d = 20; // the amount of stars to spawn every frame.
// ---------------------------------------------
var canvas = document.getElementById('c'),
ctx = canvas.getContext('2d'),
stars = [],
m = {},
r = 0
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
m.x = null;
m.y = null;
ctx.strokeStyle = '#fff';
ctx.translate(0.5, 0.5);
// create stars
function createStars(n) {
if (m.x == null) return;
for (var i = 0; i < n; i++) {
var shape = {
x: m.x,
y: m.y,
r: 1,
speed: 1,
accel: 1.01,
accel2: 0.001,
angle: Math.random() * 360
}
var vel = {
x: a * Math.cos(shape.angle * Math.PI / 180),
y: a * Math.sin(shape.angle * Math.PI / 180)
};
shape.x += vel.x;
shape.y += vel.y;
stars.push(shape);
}
}
function render() {
createStars(d);
var bench = [];
// ctx.save();
// ctx.fillStyle = 'rgba(0,0,0,0.5)';
// ctx.fillRect(0, 0, canvas.width, canvas.height);
// ctx.restore();
ctx.clearRect(0, 0, canvas.width, canvas.height);
r += c;
if (r < 360) {
m = {
x: canvas.width / 2,
y: canvas.height / 2,
angle: r
}
var targetAngle = m.angle * Math.PI / 180;
m.x += b * Math.cos(targetAngle);
m.y += b * Math.sin(targetAngle);
} else {
r = 0;
}
while (stars.length) {
var star = stars.pop();
var vel = {
x: star.speed * Math.cos(star.angle * Math.PI / 180),
y: star.speed * Math.sin(star.angle * Math.PI / 180)
};
ctx.beginPath();
ctx.moveTo(star.x, star.y);
ctx.lineTo(star.x + vel.x, star.y + vel.y);
ctx.closePath();
ctx.stroke();
star.x += vel.x;
star.y += vel.y;
star.speed *= star.accel;
star.accel += star.accel2;
if (star.x < canvas.width && star.x > 0 && star.y < canvas.height && star.y > 0) {
bench.push(star);
}
}
stars = bench.slice(0).reverse();
}
window.requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
(function animloop() {
requestAnimFrame(animloop);
render();
})();
#import url(https://fonts.googleapis.com/css?family=Hammersmith+One);
html {
margin: 0;
padding: 0;
height: 100vh;
background: #222;
color: cornflowerblue;
overflow-x: hidden;
font-size: 18px;
font-family: 'Hammersmith One', sans-serif;
}
/************************************/
#c {
height: 200px;
width: 200px;
border-radius: 50%;
border: 5px double lightgray;
margin-left: 150px;
margin-right: 150px;
background: #222;
z-index: 10;
position: absolute;
left: 0px;
top: 50px;
}
.canwrap {
background: url(http://placekitten.com/g/300/300);
height: 300px;
width: 500px;
position: relative;
z-index: 0;
margin-left: 50px;
margin-right: 50px;
}
.canwrap:before {
content: "";
position: absolute;
width: 150px;
height: 100%;
top: 0;
left: 50%;
transform: translateX(-50%);
background: #222;
z-index: -1;
}
.canwrap:after {
content: "";
position: absolute;
height: 100px;
width: 100px;
top: 100px;
left: -50px;
background: red;
border-radius: 50%;
box-shadow: 500px 0 20px -5px red;
}
<div class="canwrap">
<canvas id="c" class="img"></canvas>
</div>
However, this leaves me with a few issues:
Background part can't be an image
circles can't replicate the image part
gradient stop colours means there is not a 'clear edge' to the shape.
I would be really grateful to get another view/angle on constructing this shape, as I haven't been able to produce this in a way that I need to.
I know svg might be the way to do this, but I've always had a hard time getting svg's to animate properly compared to css - but if either work, I'd be happy (seeing as my design doesn't exactly allow my image design)!
As always, any suggestions would be great.
How about something like this i used svg Fiddle
<svg width="1000" height="500">
<polygon points="100 10, 50 245, 100 500, 200 500, 200 10,100 10" fill="orange" />
<polygon points="400 10, 460 245, 400 500, 300 500, 300 10,200 10" fill="orange" />
<circle r="50" cx="50" cy="245" fill="orange" />
<circle r="50" cx="460" cy="245" fill="orange" />
<circle r="100" cx="255" cy="245" fill="midnightblue" />
</svg>
You can also do it with image as background
<svg width="1000" height="500">
<defs>
<pattern id="pattern" patternUnits="userSpaceOnUse" width="1000" height="1000">
<image xlink:href="https://placekitten.com/g/200/300" x="-200" y="-10" width="1000" height="1000" />
</pattern>
</defs>
<polygon points="100 10, 50 245, 100 500, 200 500, 200 10,100 10" fill="url(#pattern)"/>
<polygon points="400 10, 460 245, 400 500, 300 500, 300 10,200 10" fill="url(#pattern)"/>
<circle r="50" cx="50" cy="245" fill="url(#pattern)"/>
<circle r="50" cx="460" cy="245" fill="url(#pattern)"/>
<circle r="100" cx="255" cy="245" fill="midnightblue"/>
although this is not for canvas but rather for html element you can do the same technique in canvas.
I assume you already know basic css 3,now since it's a lot of work to code, I'll give you the instructions:
1) head out to this link
2) create 2 Trapezoids and rotate them 90 degrees
3) create 2 small circles and position each one (relative/absolute) on the edge of the Trapezoid with z-index smaller than the Trapezoids
4) 1 circle in the middle and your done!
You can use svg, which simplifies the creation of shape to a large extent.
Create a path, and fill in pattern.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 65 50" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="image" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="http://www.placecage.com/g/200/300" width="50" x="-10" y="0" height="50"/>
<image xlink:href="http://www.placekitten.com/g/200/300" width="50" x="30" y="0" height="50"/>
</pattern>
</defs>
<path d="M 25 0 H 15 L 10 20 A 5.3 5.3 0 1 0 10 30 L15 50 H25 z M 40 0 H 50 L 55 20 A 5.3 5.3 0 1 1 55 30 L 50 50 H 40 z" fill="url(#image)" stroke="none"/>
</svg>
Height and width have been set to 100%, so this should be responsive. Also, the position of images can be changed using x,y attributes.

Resources