How ThumbnailViewer example has to be adapted when using <svg> instead of <embed>? - svgpanzoom

I am using the ariutta svg-pan-zoom library(https://github.com/ariutta/svg-pan-zoom).
Now I want to create a ThumbnailViewer like described in the demo files (view-source:http://ariutta.github.io/svg-pan-zoom/demo/thumbnailViewer.html).
Instead of embedding an svg.file using tag, I directly use . How I have to change the demo code that this works?
My Code ist:
<div id="mainViewContainer">
<!--<embed id="mainView" type="image/svg+xml" src="lib/svg-pan-zoom/demo/tiger.svg"/>-->
<svg id="mainView" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 800"><rect fill="#00000", x="10" y="20" width="100" height="100"></rect></svg>
</div>
<div id="thumbViewContainer" class="thumbViewClass">
<svg id="scopeContainer" viewBox="0 0 500 500">
<g>
<rect id="scope" fill="red" fill-opacity="0.1" stroke="red" stroke-width="2px" x="0" y="0" width="0" height="0"/>
<line id="line1" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
<line id="line2" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
</g>
</svg>
<svg id="thumbView" class="thumbViewClass" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 800" ><rect fill="#00000", x="10" y="20" width="100" height="100" ></rect></svg>
<!--<embed id="thumbView" type="image/svg+xml" src="lib/svg-pan-zoom/demo/tiger.svg" class="thumbViewClass"/>-->
</div>

You should use an embed element the same way as you would use an svg element.
The only difference is that you have to wait for embed element to load before initializing svgPanZoom (or thumbnail viewer) in your case.

I got it!
The main difference is with the size of the SVG loaded.
With embed, when load resize the svg automatically to the parent div, or tag container.
With svg inline, the svg is loaded, with the width and height itself properties.
I debug the library line by line, and I found that when is calculating the matrix SVG transform, takes the clientHeight and clientWidth from the SVG tag, and resize the viewport to the size I have defined above. So the short answer is, put a style height and width equal to 100%.
#id_mainSVG, #id_thumbSVG {
height: 100%;
width: 100%;
}
var thumbnailViewer = function(options) {
var getSVGDocument = function(objectElem) {
var svgDoc = objectElem.contentDocument;
if (!svgDoc) {
if (typeof objectElem.getSVGDocument === "function") {
svgDoc = objectElem.getSVGDocument();
}
}
return svgDoc;
}
var bindThumbnail = function(main, thumb, scopeContainerId) {
if (!window.main && main) {
window.main = main;
}
if (!window.thumb && thumb) {
window.thumb = thumb;
}
if (!window.main || !window.thumb) {
return;
}
var resizeTimer;
var interval = 300; //msec
window.addEventListener('resize', function(event) {
if (resizeTimer !== false) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
window.main.resize();
window.thumb.resize();
}, interval);
});
window.main.setOnZoom(function(level) {
window.thumb.updateThumbScope();
if (options.onZoom) {
options.onZoom(window.main, window.thumb, level);
}
});
window.main.setOnPan(function(point) {
window.thumb.updateThumbScope();
if (options.onPan) {
options.onPan(window.main, window.thumb, point);
}
});
var _updateThumbScope = function(main, thumb, scope, line1, line2) {
var mainPanX = main.getPan().x,
mainPanY = main.getPan().y,
mainWidth = main.getSizes().width,
mainHeight = main.getSizes().height,
mainZoom = main.getSizes().realZoom,
thumbPanX = thumb.getPan().x,
thumbPanY = thumb.getPan().y,
thumbZoom = thumb.getSizes().realZoom;
var thumByMainZoomRatio = thumbZoom / mainZoom;
var scopeX = thumbPanX - mainPanX * thumByMainZoomRatio;
var scopeY = thumbPanY - mainPanY * thumByMainZoomRatio;
var scopeWidth = mainWidth * thumByMainZoomRatio;
var scopeHeight = mainHeight * thumByMainZoomRatio;
scope.setAttribute("x", scopeX + 1);
scope.setAttribute("y", scopeY + 1);
scope.setAttribute("width", scopeWidth - 2);
scope.setAttribute("height", scopeHeight - 2);
/*
line1.setAttribute("x1", scopeX + 1);
line1.setAttribute("y1", scopeY + 1);
line1.setAttribute("x2", scopeX + 1 + scopeWidth - 2);
line1.setAttribute("y2", scopeY + 1 + scopeHeight - 2);
line2.setAttribute("x1", scopeX + 1);
line2.setAttribute("y1", scopeY + 1 + scopeHeight - 2);
line2.setAttribute("x2", scopeX + 1 + scopeWidth - 2);
line2.setAttribute("y2", scopeY + 1);
*/
};
window.thumb.updateThumbScope = function() {
// TODO: Parametrizar estas varibales id del html
var scope = document.getElementById('scope');
var line1 = document.getElementById('line1');
var line2 = document.getElementById('line2');
_updateThumbScope(window.main, window.thumb, scope, line1, line2);
}
window.thumb.updateThumbScope();
var _updateMainViewPan = function(clientX, clientY, scopeContainer, main, thumb) {
var dim = scopeContainer.getBoundingClientRect(),
mainWidth = main.getSizes().width,
mainHeight = main.getSizes().height,
mainZoom = main.getSizes().realZoom,
thumbWidth = thumb.getSizes().width,
thumbHeight = thumb.getSizes().height,
thumbZoom = thumb.getSizes().realZoom;
var thumbPanX = clientX - dim.left - thumbWidth / 2;
var thumbPanY = clientY - dim.top - thumbHeight / 2;
var mainPanX = -thumbPanX * mainZoom / thumbZoom;
var mainPanY = -thumbPanY * mainZoom / thumbZoom;
main.pan({
x: mainPanX,
y: mainPanY
});
};
var updateMainViewPan = function(evt, scopeContainerId) {
if (evt.which == 0 && evt.button == 0) {
return false;
}
var scopeContainer = document.getElementById(scopeContainerId);
_updateMainViewPan(evt.clientX, evt.clientY, scopeContainer, window.main, window.thumb);
}
var scopeContainer = document.getElementById(scopeContainerId);
scopeContainer.addEventListener('click', function(evt) {
updateMainViewPan(evt, scopeContainerId);
});
scopeContainer.addEventListener('mousemove', function(evt) {
updateMainViewPan(evt, scopeContainerId);
});
};
var initMainView = function() {
var mainViewSVGDoc = getSVGDocument(mainViewObjectElem);
if (options.onMainViewSVGLoaded) {
options.onMainViewSVGLoaded(mainViewSVGDoc);
}
var beforePan = function(oldPan, newPan) {
var stopHorizontal = false,
stopVertical = false,
gutterWidth = 100,
gutterHeight = 100
// Computed variables
,
sizes = this.getSizes(),
leftLimit = -((sizes.viewBox.x + sizes.viewBox.width) * sizes.realZoom) + gutterWidth,
rightLimit = sizes.width - gutterWidth - (sizes.viewBox.x * sizes.realZoom),
topLimit = -((sizes.viewBox.y + sizes.viewBox.height) * sizes.realZoom) + gutterHeight,
bottomLimit = sizes.height - gutterHeight - (sizes.viewBox.y * sizes.realZoom);
customPan = {};
customPan.x = Math.max(leftLimit, Math.min(rightLimit, newPan.x));
customPan.y = Math.max(topLimit, Math.min(bottomLimit, newPan.y));
return customPan;
};
var main = svgPanZoom('#' + options.mainSVGId, {
zoomEnabled: true,
controlIconsEnabled: true,
fit: true,
center: true,
beforePan: beforePan,
});
bindThumbnail(main, undefined, options.scopeContainerId);
if (options.onMainViewShown) {
options.onMainViewShown(mainViewSVGDoc, main);
}
};
var mainViewObjectElem = document.getElementById(options.mainSVGId);
mainViewObjectElem.addEventListener("load", function() {
initMainView();
}, false);
var initThumbView = function() {
var thumbViewSVGDoc = getSVGDocument(thumbViewObjectElem);
if (options.onThumbnailSVGLoaded) {
options.onThumbnailSVGLoaded(thumbViewSVGDoc);
}
var thumb = svgPanZoom('#' + options.thumbSVGId, {
fit: true,
zoomEnabled: false,
panEnabled: false,
controlIconsEnabled: false,
dblClickZoomEnabled: false,
preventMouseEventsDefault: true,
});
bindThumbnail(undefined, thumb, options.scopeContainerId);
if (options.onThumbnailShown) {
options.onThumbnailShown(thumbViewSVGDoc, thumb);
}
};
var thumbViewObjectElem = document.getElementById(options.thumbSVGId);
thumbViewObjectElem.addEventListener("load", function() {
initThumbView();
}, false);
// Se inicializan los controles
initThumbView();
initMainView();
};
body {
background: #f5f5f5;
}
html,
body {
width: 100%;
height: 100%;
}
#mainViewContainer {
width: 95%;
height: 95%;
border: 1px solid black;
margin: 10px;
padding: 3px;
overflow: hidden;
}
#mainView {
width: 100%;
height: 100%;
min-height: 100%;
display: inline;
}
.thumbViewClass {
border: 1px solid black;
position: absolute;
bottom: 5px;
left: 5px;
width: 20%;
height: 30%;
margin: 3px;
padding: 3px;
overflow: hidden;
}
#thumbSVG,
#mainSVG {
height: 100%;
width: 100%;
}
#thumbView {
z-index: 110;
background: white;
}
#scopeContainer {
z-index: 120;
}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Meta -->
<meta charset="UTF-8">
<title>My New Project!</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="http://ariutta.github.io/svg-pan-zoom/dist/svg-pan-zoom.js"></script>
</head>
<body>
<div id="mainViewContainer">
<div id="mainView">
<svg id="mainSVG" style="display: inline; width: inherit; min-width: inherit; max-width: inherit; height: inherit; min-height: inherit; max-height: inherit; " xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="linear-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(56,121,217);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(138,192,7);stop-opacity:1" />
</linearGradient>
</defs>
<g fill="none">
<g stroke="#000" fill="#FFF">
<rect x="10" y="10" width="120" height="120" fill="url(#linear-gradient)"/>
<path d="M 10 10 L 130 130 Z"/>
</g>
</g>
</svg>
</div>
</div>
<div id="thumbViewContainer">
<svg id="scopeContainer" class="thumbViewClass">
<g>
<rect id="scope" fill="red" fill-opacity="0.1" stroke="red" stroke-width="2px" x="0" y="0" width="0" height="0"/>
<line id="line1" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
<line id="line2" stroke="red" stroke-width="2px" x1="0" y1="0" x2="0" y2="0"/>
</g>
</svg>
<div id="thumbView" class="thumbViewClass">
<svg id="thumbSVG" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="linear-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(56,121,217);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(138,192,7);stop-opacity:1" />
</linearGradient>
</defs>
<g fill="none">
<g stroke="#000" fill="#FFF">
<rect x="10" y="10" width="120" height="120" fill="url(#linear-gradient)"/>
<path d="M 10 10 L 130 130 Z"/>
</g>
</g>
</svg>
</div>
</div>
<!-- Scripts -->
<script>
window.onload = function() {
thumbnailViewer({
mainSVGId: 'mainSVG',
thumbSVGId: 'thumbSVG',
scopeContainerId: 'scopeContainer'
});
}
</script>
</body>
</html>
EZ.
https://codepen.io/vquilon/pen/MWedEYE
VQR.

Related

How to make inline SVG 100% of parent container

I'm trying to make an inline SVG scale to the width of the parent element. I feel like the circle elements are causing me the issue, but I'm unsure what I should be changing to achieve it.
I have set the container to 300x300px, I have set the viewBox to "0 0 300 300". I assume I have to set the r, cx, and cy to half those? to which I have set to "150" but the circle is now getting cut off.
I have been going round in circles (excuse the pun) changing dimensions but no luck.
Your help will be greatly appreciated.
Please find a link to my codepen: https://codepen.io/MayhemBliz/pen/NWyNGxj
function circle() {
const progressRing = document.querySelector('.progress-ring');
const circle = document.querySelector('.progress-ring__bar');
const r = circle.getAttribute('r');
const percent = progressRing.dataset.percent;
const c = Math.PI * r * 2;
const pct = ((0 - percent) / 100) * c;
circle.style.strokeDashoffset = pct;
//const percentageText = document.querySelector('.percentage');
//percentageText.textContent = percent + "%";
}
window.addEventListener('load', circle);
.progress-ring {
width: 300px;
height: 300px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
}
.progress-ring__svg {
/*transform: rotate(-90deg);*/
}
.progress-ring__bar-bg, .progress-ring__bar {
stroke-dashoffset: 0;
transition: stroke-dashoffset 1s linear;
stroke: #FF9F1E;
stroke-width: 1em;
}
.progress-ring__bar {
stroke: #666;
}
.percentage {
position: absolute;
font-size: 2.5rem;
font-weight: bold;
}
<div class="progress-ring" data-percent="80">
<svg class="progress-ring__svg" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle class="progress-ring__bar-bg" r="150" cx="150" cy="150" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
<circle class="progress-ring__bar" r="150" cx="150" cy="150" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
</svg>
<span class="percentage">80%</span>
</div>
To avoid overflow you could use percentage based values for stroke-width and r (radius) like so:
<circle r="47.5%" cx="50%" cy="50%" />
or a pixel based approximation like
<circle r="142" cx="150" cy="150" />
function circle() {
const progressRing = document.querySelector('.progress-ring');
const circle = document.querySelector('.progress-ring__bar');
const r = circle.getAttribute('r');
const percent = progressRing.dataset.percent;
const c = Math.PI * r * 2;
const pct = ((0 - percent) / 100) * c;
circle.style.strokeDashoffset = pct;
//const percentageText = document.querySelector('.percentage');
//percentageText.textContent = percent + "%";
}
window.addEventListener('load', circle);
.progress-ring {
width: 300px;
/*height: 300px;*/
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
max-width:100%;
}
.progress-ring__svg {
//width:100%;
/*transform: rotate(-90deg);*/
}
.progress-ring__bar-bg, .progress-ring__bar {
stroke-dashoffset: 0;
transition: stroke-dashoffset 1s linear;
stroke: #FF9F1E;
stroke-width: 5%;
}
.progress-ring__bar {
stroke: #666;
}
.percentage {
position: absolute;
font-size: 2.5rem;
font-weight: bold;
}
.resize{
resize:both;
overflow:auto;
border: 1px solid #ccc;
padding:1em;
}
<div class="resize">
<div class="progress-ring" data-percent="80">
<svg class="progress-ring__svg" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle class="progress-ring__bar-bg" r="47.5%" cx="50%" cy="50%" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
<circle class="progress-ring__bar" r="142" cx="150" cy="150" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
<text class="percentage" x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" dy="2%">80%</text>
</svg>
</div>
</div>
<p>Resize me</p>
However, you might also use a <text> element instead of a <span> to keep the percentage text size relative to you svg boundary.

Simple svg css progress circle

I am trying to look for a way to achieve a simple progress circle (static) with no animations. The examples I have found have very different offsets for percentage such as given in the example below. How do I make my progress circle in such a way that if I provide offset as 50%, then it is exactly 50% (half filled)?
.u-absoluteCenter {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
.u-flexCenter {
display: flex;
align-items: center;
justify-content: center;
}
.u-offscreen {
position: absolute;
left: -999em;
}
.demo {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
}
.progress {
transform: rotate(-90deg);
}
.progress__value {
stroke-dasharray: 0;
stroke-dashoffset: 0;
}
#-webkit-keyframes progress {
from {
stroke-dashoffset: 339.292;
}
to {
stroke-dashoffset: 0;
}
}
#keyframes progress {
from {
stroke-dashoffset: 339.292;
}
to {
stroke-dashoffset: 0;
}
}
<svg width="120" height="120" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
<circle cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12"
stroke-dasharray="339.292" stroke-dashoffset="339.292" />
</svg>
You can leverage an SVG attribute to set the path length rather than having to calculate it.
pathLength sets the length to whatever you need...say 100 for a progress bar.
The pathLength attribute lets authors specify a total length for the path, in user units. This value is then used to calibrate the browser's distance calculations with those of the author, by scaling all distance computations using the ratio pathLength/(computed value of path length).
pathLength="100"
Then you can set the stroke-dasharray to 100 as well and then adjust the stroke-dashoffset as needed....
::root {
--val: 0;
}
svg {
transform: rotate(-90deg);
}
.percent {
stroke-dasharray: 100;
stroke-dashoffset: calc(100 - var(--val));
}
.fifty {
--val: 50;
}
.sixty {
--val: 60;
}
.ninety {
--val: 90;
}
<svg width="120" height="120" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
<circle class="percent fifty" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>
<svg width="120" height="120" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
<circle class="percent sixty" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>
<svg width="120" height="120" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="54" fill="none" stroke="#e6e6e6" stroke-width="12" />
<circle class="percent ninety" cx="60" cy="60" r="54" fill="none" stroke="#f77a52" stroke-width="12" pathLength="100" />
</svg>
As Paulie says, pathLength is the key to progress circles
A modern Custom Element (supported in all modern browsers) makes for a re-usable HTML Element
<svg-progress-circle percent="30"></svg-progress-circle>
<svg-progress-circle percent="20" color="blue"></svg-progress-circle>
<svg-progress-circle percent="80" color="gold"></svg-progress-circle>
Added a range-input for interactive demo purposes.
Percent is a property on the element, you can set with code like:
document.getElementById("Slider1").percent = <PERCENTAGE>;
If you don't want a dashed grey fullcircle, delete the dash setting from the pathLenght=120 path
I used a path instead of overlapping circles because with some other settings the almost same code can create pie-charts.
<style>
svg { width: 150px; background: teal }
svg-progress-circle[percent="100"] path { stroke: green }
</style>
<svg-progress-circle percent="30"></svg-progress-circle>
<svg-progress-circle percent="20" color="blue"></svg-progress-circle>
<svg-progress-circle percent="80" color="gold"></svg-progress-circle>
<script>
customElements.define("svg-progress-circle", class extends HTMLElement {
connectedCallback() {
let d = 'M5,30a25,25,0,1,1,50,0a25,25,0,1,1,-50,0'; // circle
this.innerHTML =
`<input type="range" min="0" max="100" step="10" value="30"`+ // delete 2 lines
` oninput="this.parentNode.percent=this.value" /><br>`+ // just for demo
`<svg viewBox="0 0 60 60">
<path stroke-dasharray="10 2" stroke-dashoffset="-19"
pathlength="120" d="${d}" fill="grey" stroke="lightgrey" stroke-width="5"/>
<path stroke-dasharray="30 70" stroke-dashoffset="-25"
pathlength="100" d="${d}" fill="none"
stroke="${this.getAttribute("color")||"red"}" stroke-width="5"/>
<text x="50%" y="57%" text-anchor="middle">30%</text></svg>`;
this.style.display='inline-block';
this.percent = this.getAttribute("percent");
}
set percent(val = 0) {
this.setAttribute("percent", val);
let dash = val + " " + (100 - val);
this.querySelector("path+path").setAttribute('stroke-dasharray', dash);
this.querySelector("text").innerHTML = val + "%";
this.querySelector("input").value = val;
}
})
</script>
Note: I am working on a complete Web Component that does Pie Graphs and fancy Progress circles like:
But, it is one of many side-projects... HTML examples and obfuscated source code available at https://pie-meister.github.io/

SVG/Layer not working in IE and Webkit, Firefox is fine though

I'm completely stuck, i really need help guys!
Below are my snippets, which i've trimmed down as much as possible and edited a bit to show correctly on jsfiddle.
Also here is the JSFiddle: https://jsfiddle.net/oqfdfart/9/
What i need: a transparent half circle in my header that lets through my bg image, but also has a border. I managed to do this with 2 SVG's.
However only firefox shows everything fine, but all other browsers don't.
I'm eternally grateful for any help!
$(document).ready(function() {
var $myCarousel = $('#myCarousel');
function setCaptTotalheight(captid, maxheight) {
setTimeout(function() {
sliderheight = $('#slideimg' + captid).height();
//alert(sliderheight);
if (sliderheight > 0) {
if (sliderheight > maxheight) {
useheight = maxheight;
} else {
useheight = sliderheight;
}
$('.container-carousel').attr('style', 'height:' + useheight + 'px;padding:0px; overflow:hidden;');
$('.header-carousel').attr('style', 'height:' + useheight + 'px; overflow:hidden;');
$('#slide' + captid).attr('style', 'height:' + useheight + 'px;');
}
}, 5);
}
function setCaptheight(captid, maxheight) {}
var $navElemsId = $myCarousel.find('.item:first').attr('data-id');
var $navElemsCenter = $myCarousel.find('.item:first').attr('data-center');
var $navElemsMaxHeight = $myCarousel.find('.item:first').attr('data-maxheight');
if ($navElemsCenter == 1) {
setCaptTotalheight($navElemsId, $navElemsMaxHeight);
setCaptheight($navElemsId, $navElemsMaxHeight);
}
if ($navElemsCenter == 2) {
setCaptTotalheight($navElemsId, $navElemsMaxHeight);
}
});
#import url( 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css' );
#import url( 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' );
body{
background: #eee;
}
#headeroverlay {
width: 100%;
height: 100%;
}
.carousel {
background: url(http://placehold.it/230x50) no-repeat 50% 95%;
}
#myCarousel .item {
border-bottom: 5px solid #942994;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: hidden;
mask: url(#mask);
}
.nopadding {
padding: 0;
}
#headeroverlay {
width: 100%;
position: absolute;
top:0;
background: rgba(255,255,255,0);
height: 223px;
z-index: auto;
}
#innercircle {
position: absolute;
top: 0;
left: 0;
}
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="mp-pusher maincontainer maincontainer-602" id="mp-pusher" style="position:inherit">
<div class="container-fluid container-fluid-header header-container-above-menu container-carousel" style="height:auto; max-height:499px; overflow:hidden; padding:0px;"><!-- start carousel -->
<div id="myCarousel" class="carousel carousel-fade slide myCarousel-slide" style="height:auto; max-height:499px; overflow:hidden">
<div class="carousel-inner" role="listbox">
<div id="slide2" class="item active" data-navpos="" data-navposarrow="" data-center="1" data-maxheight="499" data-id="2" style=""><img id="slideimg2" class="logofull img-responsive" src="http://placehold.it/1920x499" /></div>
</div>
</div>
<section id="headeroverlay" class="headeroverlay">
<svg width="100%" height="100%">
<defs>
<style type="text/css"><![CDATA[
#inner {
stroke: #942994;
stroke-width: 5;
fill-opacity: 0;
z-index: 9999;
}
]]></style>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<circle id="c1" cx="50%" cy="105%" r="180" fill="#000"/>
</mask>
</defs>
<rect x="0" y="0" width="100" height="50" mask="url(#mask)" fill-opacity="0"/>
</svg>
<svg id="innercircle" width="100%" height="100%" x="0" y="0">
<circle id="inner" x="0" y="0" cx="50%" cy="105%" r="181" fill="#fff" />
</svg>
</section>
</div>

Circular percent progress bar

I would like to have an percent circle indicator on my site:
In this case it's showing 75%. How should this be done? I have the yellow circle in a image-file, but if it's easier to, some how, do it all using CSS, that's okay with me.
Considering the shape of the progress bar (rounded end/start) I would suggest using SVG.
DEMO: Radial progress bar
In the following example, the progress is animated with the stroke-dasarray attribute and the % numbers are incremented with jQuery:
var count = $(('#count'));
$({ Counter: 0 }).animate({ Counter: count.text() }, {
duration: 5000,
easing: 'linear',
step: function () {
count.text(Math.ceil(this.Counter)+ "%");
}
});
body{text-align:center;font-family: 'Open Sans', sans-serif;}
svg{width:25%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="animated" viewbox="0 0 100 100">
<circle cx="50" cy="50" r="45" fill="#FDB900"/>
<path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
stroke-dasharray="251.2,0"
d="M50 10
a 40 40 0 0 1 0 80
a 40 40 0 0 1 0 -80">
<animate attributeName="stroke-dasharray" from="0,251.2" to="251.2,0" dur="5s"/>
</path>
<text id="count" x="50" y="50" text-anchor="middle" dy="7" font-size="20">100%</text>
</svg>
Unfortunatly IE doesn't support svg SMIL animations. To achieve the same result with IE support, you can use a library like snap.svg and animate the stroke-dasharray attribute with JS :
var count = $(('#count'));
$({ Counter: 0 }).animate({ Counter: count.text() }, {
duration: 5000,
easing: 'linear',
step: function () {
count.text(Math.ceil(this.Counter)+ "%");
}
});
var s = Snap('#animated');
var progress = s.select('#progress');
progress.attr({strokeDasharray: '0, 251.2'});
Snap.animate(0,251.2, function( value ) {
progress.attr({ 'stroke-dasharray':value+',251.2'});
}, 5000);
body{text-align:center;font-family:sans-serif;}
svg{width:25%;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js"></script>
<svg id="svg" viewbox="0 0 100 100">
<circle cx="50" cy="50" r="45" fill="#FDB900"/>
<path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
stroke-dasharray="1,250.2"
d="M50 10
a 40 40 0 0 1 0 80
a 40 40 0 0 1 0 -80"/>
<text x="50" y="50" text-anchor="middle" dy="7" font-size="20">1%</text>
</svg>
<svg viewbox="0 0 100 100">
<circle cx="50" cy="50" r="45" fill="#FDB900"/>
<path fill="none" stroke-linecap="round" stroke-width="5" stroke="#fff"
stroke-dasharray="125.6,125.6"
d="M50 10
a 40 40 0 0 1 0 80
a 40 40 0 0 1 0 -80"/>
<text x="50" y="50" text-anchor="middle" dy="7" font-size="20">50%</text>
</svg>
<svg id="animated" viewbox="0 0 100 100">
<circle cx="50" cy="50" r="45" fill="#FDB900"/>
<path id="progress" stroke-linecap="round" stroke-width="5" stroke="#fff" fill="none"
d="M50 10
a 40 40 0 0 1 0 80
a 40 40 0 0 1 0 -80">
</path>
<text id="count" x="50" y="50" text-anchor="middle" dy="7" font-size="20">100%</text>
</svg>
Pure HTML/CSS Solution
In short, I used the CSS border-radius and z-index properties to create a white half circle layered beneath an orange center circle and orange outer ring. Initially, the half-circle is completely hidden behind an additional layer of orange on the left side, but its outer edge is gradually revealed as it rotates around the center axis (via CSS transform: rotate()), creating the appearance of a progress bar. Additional trickery is required once the progress bar passes the halfway point (see below the snippet for more info).
All of this was done with pure HTML and CSS, except the animation, which uses JavaScript. It may appear to require more code than the SVG-based solutions, but the markup is actually much simpler, which makes it a good alternative in my opinion.
function setProgress(elem, percent) {
var
degrees = percent * 3.6,
transform = /MSIE 9/.test(navigator.userAgent) ? 'msTransform' : 'transform';
elem.querySelector('.counter').setAttribute('data-percent', Math.round(percent));
elem.querySelector('.progressEnd').style[transform] = 'rotate(' + degrees + 'deg)';
elem.querySelector('.progress').style[transform] = 'rotate(' + degrees + 'deg)';
if(percent >= 50 && !/(^|\s)fiftyPlus(\s|$)/.test(elem.className))
elem.className += ' fiftyPlus';
}
(function() {
var
elem = document.querySelector('.circlePercent'),
percent = 0;
(function animate() {
setProgress(elem, (percent += .25));
if(percent < 100)
setTimeout(animate, 15);
})();
})();
.circlePercent {
position: relative;
top: 26px;
left: 26px;
width: 96px;
height: 96px;
border-radius: 50%;
background: orange;
}
.circlePercent:before,
.circlePercent > .progressEnd {
position: absolute;
z-index: 3;
top: 2px;
left: 45px;
width: 6px;
height: 6px;
border-radius: 50%;
background: white;
-ms-transform-origin: 3px 46px;
transform-origin: 3px 46px;
content: "";
}
.circlePercent:after,
.circlePercent > .progress {
position: absolute;
-ms-transform-origin: 48px 48px;
transform-origin: 48px 48px;
z-index: 0;
top: 0;
left: 0;
width: 48px;
height: 96px;
border-radius: 48px 0 0 48px;
background: orange;
content: "";
}
.circlePercent.fiftyPlus:after {
background: white;
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.circlePercent > .progress.progress {
background: white;
}
.circlePercent > .counter {
position: absolute;
box-sizing: border-box;
z-index: 2;
width: 100px;
height: 100px;
margin-top: -2px;
margin-left: -2px;
border-radius: 50%;
border: 4px solid orange;
}
.circlePercent > .counter:before {
position: absolute;
z-index: 1;
top: 50%;
margin-top: -13px;
width: 100%;
height: 26px;
font-size: 26px;
line-height: 26px;
font-family: sans-serif;
text-align: center;
color: white;
content: attr(data-percent) "%";
}
.circlePercent > .counter:after {
position: absolute;
width: 80px;
height: 80px;
top: 6px;
left: 6px;
border-radius: 50%;
background: orange;
content: "";
}
.circlePercent > .counter[data-percent="100"] {
background: white;
}
<div class="circlePercent">
<div class="counter" data-percent="0"></div>
<div class="progress"></div>
<div class="progressEnd"></div>
</div>
Notice that the fiftyPlus class is added to the container element once the progress bar reaches the halfway point. This adds a static progress bar to the right half of the circle. Without it, the progress will appear to drain out of the right side instead of filling in the left side.
Demo : CODEPEN
Here is my attempt at getting the percentage circle indicator:
Path draws two arches and i set the stroke-dasharray.
we don't really need to set the dasharray since we set that later with javascript.
Html
<svg class="circles" viewbox="0 0 200 200">
<g id="first">
<circle r="50" cx="100" cy="100" fill="#fb0"/>
<path fill="none"
stroke-linecap="round"
stroke-width="7"
stroke="#ffa"
stroke-dasharray="250,250"
d="M100 60
A1 1 0 0 1 100 140
A1 1 0 0 1 100 60"/>
<text class="circ-text"
text-anchor="middle"
x="100" y="100"
font-size="12px"
fill="#ffa"
>percentage
</text>
</g>
</svg>
Javascirpt
Get the path with #first path.
Get the length of the dash-array: path.getTotalLength();
Increase the dash-array until its full: setAttribute('stroke-dasharray', i+","+length); Where i is increased.
Find out what percentage we are at: (count++/ticks)*100
add the percentage to the svg text: text.innerHTML=(count/tick)*100
var path = document.querySelector('#first path');
var text = document.querySelector('#first .circ-text');
var length = path.getTotalLength();
var i = 0;
var count = 0;
var ticks = 50;
setInterval(function() {
if (i < length+length/ticks) {
path.setAttribute('stroke-dasharray', i+","+length);
i+=length/ticks;
text.innerHTML=Math.round((count++/ticks)*100);
}
}, 100);
var path = document.querySelector('#first path');
var text = document.querySelector('#first .circ-text');
var length = path.getTotalLength();
var i = 0;
var count = 0;
var ticks = 50;
setInterval(function() {
if (i < length+length/ticks) {
path.setAttribute('stroke-dasharray', i+","+length);
i+=length/ticks;
text.innerHTML=Math.round((count++/ticks)*100);
}
}, 100);
<svg class="circles" viewbox="0 0 500 200">
<g id="first">
<circle r="50" cx="100" cy="100" fill="#fb0" />
<path fill="none" stroke-linecap="round" stroke-width="7" stroke="#ffa" stroke-dasharray="250,250" d="M100 60 A1 1 0 0 1 100 140
A1 1 0 0 1 100 60" />
<text class="circ-text" text-anchor="middle" x="100" y="100" font-size="12px" fill="#ffa">percentage</text>
</g>
Circular Percent Progress bar using Canvas ...
var ctx = document.getElementById('circularLoader').getContext('2d');
var al = 0;
var start = 4.72;
var cw = ctx.canvas.width;
var ch = ctx.canvas.height;
var diff;
function progressSim(){
diff = ((al / 100) * Math.PI*2*10).toFixed(2);
ctx.clearRect(0, 0, cw, ch);
ctx.lineWidth = 17;
ctx.fillStyle = '#4285f4';
ctx.strokeStyle = "#4285f4";
ctx.textAlign = "center";
ctx.font="28px monospace";
ctx.fillText(al+'%', cw*.52, ch*.5+5, cw+12);
ctx.beginPath();
ctx.arc(100, 100, 75, start, diff/10+start, false);
ctx.stroke();
if(al >= 100){
clearTimeout(sim);
// Add scripting here that will run when progress completes
}
al++;
}
var sim = setInterval(progressSim, 50);
<div id="loader">
<canvas id="circularLoader" width="200" height="200"></canvas>
</div>
See Demo :- http://codingflag.in/mysketch.php?sketch=9
Have you tried this?
<percent-display percent="75" side="" colors=""></percent-display>
Source: http://angularscript.com/angularjs-round-percentage-bar-directive-ngpercentdisplay/

SVG inside CSS, image shrinking

What would cause the resizing of an image(svg in this case) when moved from inside the html, to its on css file. I have an image that sits over top the background, and uses an svg mask to reveal the underlying background image when the mouse hovers over part of it. This works just fine! However, when I move the css and the javascript to its own file, instead of all in the same html file, the top image(inside the svg) shrinks down to a small size. any help on why this is happening would be appreciated thanks!
this is the original which works perfectly.
<!DOCTYPE html>
<html>
<head>
<script type="application/javascript" src="mouseOverJS.js"></script>
<style>
svg {
width: 856px;
height: 856px;
}
body {
background-color: white;
background-image: url("lolMap.png");
background-repeat: no-repeat;
margin: 0; padding:0;
}
image:hover {
mask: url("#cursorMask");
}
p{
margin: 0; padding:0;
}
</style>
</head>
<body>
<p>
<svg>
<mask id="cursorMask" maskUnits="objectBoundingBox" maskContentUtils="objectBoundingBox">
<defs>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="8" />
</filter>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="50%" style="stop-color:rgb(0,0,0); stop-opacity:2" />
<stop offset="75%" style="stop-color:rgb(0,0,0); stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,0,0);stop-opacity:0" />
</radialGradient>
</defs>
<g>
<!-- the SECOND rect element is what determines the transparent area -->
<rect x="0" y="0" width="856" height="856" fill="#FFFFFF" />
<circle cx="0" cy="0" r="100" fill="url(#grad1)" />
</g>
</mask>
</defs>
<image width="856" height="856" xlink:href="lolMapDark.png" />
</svg>
</p>
</body>
this is the CSS stylesheet with the same info just in its own file this time.
svg {
width: 856px;
height: 856px;
}
body {
background-color: white;
background-image: url("lolMap.png");
background-repeat: no-repeat;
margin: 0; padding:0;
}
image:hover {
mask: url("#cursorMask");
}
p{
margin: 0; padding:0;
}
this is the js file
window.addEventListener("load", function() {
var img = document.getElementsByTagName("image")[0];
var imgPos = img.getBoundingClientRect();
var imgX = imgPos.left;
var imgY = imgPos.top;
var circle = document.getElementsByTagName("circle")[0];
var circleRadius = circle.getAttribute("r") / 2;
img.addEventListener("mousemove", function (e) {
circle.setAttribute("cx", e.clientX - imgX);
circle.setAttribute("cy", e.clientY - imgY);
}, false);
}, false);
I also swapped out the style tags with
<link rel="stylesheet" type="text/css" href="mouseOverCSS.css">
Take a look at setting the 'viewbox`; sizing/resizing can generally be controlled with height/width and viewbox.
<svg width="856" height="856" viewbox="0 0 856 856">
It is also possible that the external reference is not getting applied for some reason ... check the Console/Network and Inspector; looking for errors loading in the console/network and check the element within the Inspector to see what CSS is being applied.
Reference: http://tutorials.jenkov.com/svg/svg-viewport-view-box.html