Error: <tspan> attribute dy: Expected length, "NaN" - Raphael.js - javascript

I've got a lot of errors when hiding/showing object made in raphael.
I have a house made with raphael - when button clicked a gauge is shown and animating, if you click again the house is showing and animating again (function running over and over again when clicking)
This function is showing on phone, on normal desktop the function isn't used. So therefor I can't just put the function on the button.
BUT! I got a lot of errors when doing it.
Made a fiddle showing it. See it here.
Full js code here:
pv = 80;
pointerv = Math.round(pv);
onload = function() {
$(function dogauge() {
var Needle, arc, arcEndRad, arcStartRad, barWidth, chart, chartInset, degToRad, el, endPadRad, height, i, margin, needle, numSections, padRad, percToDeg, percToRad, percent, radius, ref, sectionIndx, sectionPerc, startPadRad, svg, totalPercent, width;
percent = pointerv/100;
barWidth = 40;
numSections = 3;
// / 2 for HALF circle
sectionPerc = 1 / numSections / 2;
padRad = 0.05;
chartInset = 10;
// start at 270deg
totalPercent = .75;
el = d3.select('.chart-gauge');
margin = {
top: 20,
right: 20,
bottom: 30,
left: 20
};
width = el[0][0].offsetWidth - margin.left - margin.right;
height = width;
radius = Math.min(width, height) / 2;
percToDeg = function(perc) {
return perc * 360;
};
percToRad = function(perc) {
return degToRad(percToDeg(perc));
};
degToRad = function(deg) {
return deg * Math.PI / 180;
};
svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);
chart = svg.append('g').attr('transform', `translate(${(width + margin.left) / 2}, ${(height + margin.top) / 2})`);
// build gauge bg
for (sectionIndx = i = 1, ref = numSections; (1 <= ref ? i <= ref : i >= ref); sectionIndx = 1 <= ref ? ++i : --i) {
arcStartRad = percToRad(totalPercent);
arcEndRad = arcStartRad + percToRad(sectionPerc);
totalPercent += sectionPerc;
startPadRad = sectionIndx === 0 ? 0 : padRad / 2;
endPadRad = sectionIndx === numSections ? 0 : padRad / 2;
arc = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth).startAngle(arcStartRad + startPadRad).endAngle(arcEndRad - endPadRad);
chart.append('path').attr('class', `arc chart-color${sectionIndx}`).attr('d', arc);
}
Needle = class Needle {
constructor(len, radius1) {
this.len = len;
this.radius = radius1;
}
drawOn(el, perc) {
el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
return el.append('path').attr('class', 'needle').attr('d', this.mkCmd(perc));
}
animateOn(el, perc) {
var self;
self = this;
return el.transition().delay(500).ease('elastic').duration(3000).selectAll('.needle').tween('progress', function() {
return function(percentOfPercent) {
var progress;
progress = percentOfPercent * perc;
return d3.select(this).attr('d', self.mkCmd(progress));
};
});
}
mkCmd(perc) {
var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
thetaRad = percToRad(perc / 2); // half circle
centerX = 0;
centerY = 0;
topX = centerX - this.len * Math.cos(thetaRad);
topY = centerY - this.len * Math.sin(thetaRad);
leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);
return `M ${leftX} ${leftY} L ${topX} ${topY} L ${rightX} ${rightY}`;
}
};
needle = new Needle(90, 15);
needle.drawOn(chart, 0);
needle.animateOn(chart, percent);
});
$(function dohouse() {
var paper = Raphael("frivardihouse", 250, 260);
paper.customAttributes.step = function (s) {
var len = this.orbit.getTotalLength();
var point = this.orbit.getPointAtLength(s * len);
return {
transform: "t" + [point.x, point.y] + "r" + point.alpha
};
};
var bghouse = paper.path("M236.5,80.4L128.9,2.1c-1.6-1.1-3.7-1.1-5.3,0L16.1,80.4c-3.5,2.6-1.7,8.1,2.6,8.1l13,0c-1,2.5-1.5,5.3-1.5,8.2l0,122.7c0,12,9.2,21.7,20.6,21.7l150.9,0c11.4,0,20.6-9.7,20.6-21.7l0-122.7c0-2.9-0.5-5.7-1.5-8.2h13C238.2,88.6,240,83,236.5,80.4z").attr({fill: "#cccccc", stroke: "none"});
bghouse.glow({
width:10,
fill:true,
offsetx :0,
offsety:3,
color:'#bfbfbf'
}
);
function formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.')
}
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
let ltv = (100 - 80)/100;
/*let vardi = <?=$graph->CurrentPropValue?>;
let boligvardi = "Boligværdi " + formatNumber(vardi);
let boligvardilink = boligvardi.link("https://realkreditkonsulenten.dk/kundeportal/?page=property");*/
let equity = 20;
let h = 144*ltv;
let y = 86+((1-ltv)*144);
let EqText = formatNumber (equity);
let ltvtxt = round(ltv * 100);
var green = "#59ba41";
var darkgreen = "#1a7266";
var yellow = "#fbb732";
var red = "#c80000";
var finalfillcolor = green;
if (ltv > 0.6) {
finalfillcolor = darkgreen;
}
if (ltv > 0.82) {
finalfillcolor = yellow;
}
if (ltv > 0.95) {
finalfillcolor = red;
}
if (ltv > 1) {
h = 144;
y= 88;
}
var fillhouse = paper.rect(40.5,230,172.3,0).attr({fill: green, stroke: "none"});
/*skal hides hvis function mus kører*/
var sAnimation = Raphael.animation({ 'width': 172.3, 'height': h, 'x': 40.5, 'y': y, fill: finalfillcolor}, 2000, "backOut")
fillhouse.animate(sAnimation);
var thehouse = paper.path("M236.5,80.4L128.9,2.1c-1.6-1.1-3.7-1.1-5.3,0L16.1,80.4c-3.5,2.6-1.7,8.1,2.6,8.1l13,0c-1,2.5-1.5,5.3-1.5,8.2l0,122.7c0,12,9.2,21.7,20.6,21.7l150.9,0c11.4,0,20.6-9.7,20.6-21.7l0-122.7c0-2.9-0.5-5.7-1.5-8.2h13C238.2,88.6,240,83,236.5,80.4z M206.7,104.9l0,106.5c0,9-6.9,16.3-15.5,16.3l-129.9,0c-8.5,0-15.5-7.3-15.5-16.3l0-106.5c0-9,6.9-16.3,15.5-16.3l129.9,0C199.8,88.6,206.7,95.9,206.7,104.9z").attr({fill: "#ffffff", stroke: "none"});
var txtbelaning = paper.text(126.8,198, "BELÅNING").attr({"font-family": "Open sans", "font-weight":"700", "font-size": 20, "transform": "matrix(1 0 0 1 79.455 216.7752)", "fill":"#ffffff"});
/*var housevalue = paper.text(126.8,210, boligvardi).attr({"font-family": "Open sans", "font-weight":"400", "font-size": 13, "fill":"#ffffff"});*/
paper.customAttributes.txtprc = function (txtprc) {
return {
txtprc: [txtprc],
text: Math.floor(txtprc) +"%" + '\n'
}
}
var txtprc = paper
.text(126.1,158.2)
.attr({
"font-size": 48,
"fill": "#ffffff",
"font-family":"Open sans",
"font-weight":"700",
txtprc: [0,1000]
})
txtprc.animate({
txtprc: [ltvtxt, 1000]
}, 2000, "easeInOut")
var txtfrivardi = paper.text(126.8,42.1, "FRIVÆRDI").attr({"font-family": "Open sans", "font-weight":"600", "font-size": 12, "transform": "matrix(1 0 0 1 98.6264 51.0823)", "fill":"#585857"});
paper.customAttributes.txtfrivardival = function (txtfrivardival) {
return {
txtfrivardival: [txtfrivardival],
text: formatNumber(Math.floor(txtfrivardival)) + '\n'
}
}
var txtfrivardival = paper
.text(126.2,61.3)
.attr({
"font-size": 20,
"fill": "#585857",
"font-family":"Open sans",
"font-weight":"700",
txtfrivardival: [0,1000]
})
txtfrivardival.animate({
txtfrivardival: [equity, 1000]
}, 2000, "easeInOut")
});
};
$("#segaugeknap").click(function() {
if($(this).text()=== "OVERVÅGNINGSBAROMETER"){
$(this).text("TILBAGE");
document.getElementById('chart-gauge').innerHTML = '';
onload();
}
else{
$(this).text("OVERVÅGNINGSBAROMETER");
}
$('#frivardihouse, #housevalue_f, #gaugebox').slideToggle('slow');
document.getElementById('frivardihouse').innerHTML = '';
onload();
});

to get rid of the multiple houses and visible multiple gauges
$("#segaugeknap").click(function() {
if($(this).text()=== "OVERVÅGNINGSBAROMETER"){
$(this).text("TILBAGE");
document.getElementById('chart-gauge').innerHTML = '';
onload();
} else{
$(this).text("OVERVÅGNINGSBAROMETER");
document.getElementById('frivardihouse').innerHTML = '';
onload();
}
$('#frivardihouse, #housevalue_f, #gaugebox').slideToggle('slow');
});
You still have multiple gauges when house is shown.
tspan errors only happen when animation is still going. With above modification it only happens when gauge is still animating.

You shouldn't start drawing the 2 svg each time you click the bottun
So first step is to seperate the 2 drawing function and remove the onload wrapper function.
Then when you click on the guage button is to wait until the slide animation complete so we can calculate the width and height for the guage container Div after that is to draw the gauge and same for the house.
Please check the following jsfiddle i've forked yours and do the changes hope it's clear for you.
Check the fiddle https://jsfiddle.net/tb1k5sgc/
pv = 80;
pointerv = Math.round(pv);
function dogauge() {
var Needle, arc, arcEndRad, arcStartRad, barWidth, chart, chartInset, degToRad, el, endPadRad, height, i, margin, needle, numSections, padRad, percToDeg, percToRad, percent, radius, ref, sectionIndx, sectionPerc, startPadRad, svg, totalPercent, width;
percent = pointerv/100;
barWidth = 40;
numSections = 3;
// / 2 for HALF circle
sectionPerc = 1 / numSections / 2;
padRad = 0.05;
chartInset = 10;
// start at 270deg
totalPercent = .75;
el = d3.select('.chart-gauge');
margin = {
top: 20,
right: 20,
bottom: 30,
left: 20
};
width = el[0][0].offsetWidth - margin.left - margin.right;
height = width;
radius = Math.min(width, height) / 2;
percToDeg = function(perc) {
return perc * 360;
};
percToRad = function(perc) {
return degToRad(percToDeg(perc));
};
degToRad = function(deg) {
return deg * Math.PI / 180;
};
svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);
chart = svg.append('g').attr('transform', `translate(${(width + margin.left) / 2}, ${(height + margin.top) / 2})`);
// build gauge bg
for (sectionIndx = i = 1, ref = numSections; (1 <= ref ? i <= ref : i >= ref); sectionIndx = 1 <= ref ? ++i : --i) {
arcStartRad = percToRad(totalPercent);
arcEndRad = arcStartRad + percToRad(sectionPerc);
totalPercent += sectionPerc;
startPadRad = sectionIndx === 0 ? 0 : padRad / 2;
endPadRad = sectionIndx === numSections ? 0 : padRad / 2;
arc = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth).startAngle(arcStartRad + startPadRad).endAngle(arcEndRad - endPadRad);
chart.append('path').attr('class', `arc chart-color${sectionIndx}`).attr('d', arc);
}
Needle = class Needle {
constructor(len, radius1) {
this.len = len;
this.radius = radius1;
}
drawOn(el, perc) {
el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
return el.append('path').attr('class', 'needle').attr('d', this.mkCmd(perc));
}
animateOn(el, perc) {
var self;
self = this;
return el.transition().delay(500).ease('elastic').duration(3000).selectAll('.needle').tween('progress', function() {
return function(percentOfPercent) {
var progress;
progress = percentOfPercent * perc;
return d3.select(this).attr('d', self.mkCmd(progress));
};
});
}
mkCmd(perc) {
var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
thetaRad = percToRad(perc / 2); // half circle
centerX = 0;
centerY = 0;
topX = centerX - this.len * Math.cos(thetaRad);
topY = centerY - this.len * Math.sin(thetaRad);
leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);
return `M ${leftX} ${leftY} L ${topX} ${topY} L ${rightX} ${rightY}`;
}
};
needle = new Needle(90, 15);
needle.drawOn(chart, 0);
needle.animateOn(chart, percent);
};
function dohouse() {
var paper = Raphael("frivardihouse", 250, 260);
paper.customAttributes.step = function (s) {
var len = this.orbit.getTotalLength();
var point = this.orbit.getPointAtLength(s * len);
return {
transform: "t" + [point.x, point.y] + "r" + point.alpha
};
};
var bghouse = paper.path("M236.5,80.4L128.9,2.1c-1.6-1.1-3.7-1.1-5.3,0L16.1,80.4c-3.5,2.6-1.7,8.1,2.6,8.1l13,0c-1,2.5-1.5,5.3-1.5,8.2l0,122.7c0,12,9.2,21.7,20.6,21.7l150.9,0c11.4,0,20.6-9.7,20.6-21.7l0-122.7c0-2.9-0.5-5.7-1.5-8.2h13C238.2,88.6,240,83,236.5,80.4z").attr({fill: "#cccccc", stroke: "none"});
bghouse.glow({
width:10,
fill:true,
offsetx :0,
offsety:3,
color:'#bfbfbf'
}
);
function formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.')
}
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
let ltv = (100 - 80)/100;
/*let vardi = <?=$graph->CurrentPropValue?>;
let boligvardi = "Boligværdi " + formatNumber(vardi);
let boligvardilink = boligvardi.link("https://realkreditkonsulenten.dk/kundeportal/?page=property");*/
let equity = 20;
let h = 144*ltv;
let y = 86+((1-ltv)*144);
let EqText = formatNumber (equity);
let ltvtxt = round(ltv * 100);
var green = "#59ba41";
var darkgreen = "#1a7266";
var yellow = "#fbb732";
var red = "#c80000";
var finalfillcolor = green;
if (ltv > 0.6) {
finalfillcolor = darkgreen;
}
if (ltv > 0.82) {
finalfillcolor = yellow;
}
if (ltv > 0.95) {
finalfillcolor = red;
}
if (ltv > 1) {
h = 144;
y= 88;
}
var fillhouse = paper.rect(40.5,230,172.3,0).attr({fill: green, stroke: "none"});
/*skal hides hvis function mus kører*/
var sAnimation = Raphael.animation({ 'width': 172.3, 'height': h, 'x': 40.5, 'y': y, fill: finalfillcolor}, 2000, "backOut")
fillhouse.animate(sAnimation);
var thehouse = paper.path("M236.5,80.4L128.9,2.1c-1.6-1.1-3.7-1.1-5.3,0L16.1,80.4c-3.5,2.6-1.7,8.1,2.6,8.1l13,0c-1,2.5-1.5,5.3-1.5,8.2l0,122.7c0,12,9.2,21.7,20.6,21.7l150.9,0c11.4,0,20.6-9.7,20.6-21.7l0-122.7c0-2.9-0.5-5.7-1.5-8.2h13C238.2,88.6,240,83,236.5,80.4z M206.7,104.9l0,106.5c0,9-6.9,16.3-15.5,16.3l-129.9,0c-8.5,0-15.5-7.3-15.5-16.3l0-106.5c0-9,6.9-16.3,15.5-16.3l129.9,0C199.8,88.6,206.7,95.9,206.7,104.9z").attr({fill: "#ffffff", stroke: "none"});
var txtbelaning = paper.text(126.8,198, "BELÅNING").attr({"font-family": "Open sans", "font-weight":"700", "font-size": 20, "transform": "matrix(1 0 0 1 79.455 216.7752)", "fill":"#ffffff"});
/*var housevalue = paper.text(126.8,210, boligvardi).attr({"font-family": "Open sans", "font-weight":"400", "font-size": 13, "fill":"#ffffff"});*/
paper.customAttributes.txtprc = function (txtprc) {
return {
txtprc: [txtprc],
text: Math.floor(txtprc) +"%" + '\n'
}
}
var txtprc = paper
.text(126.1,158.2)
.attr({
"font-size": 48,
"fill": "#ffffff",
"font-family":"Open sans",
"font-weight":"700",
txtprc: [0,1000]
})
txtprc.animate({
txtprc: [ltvtxt, 1000]
}, 2000, "easeInOut")
var txtfrivardi = paper.text(126.8,42.1, "FRIVÆRDI").attr({"font-family": "Open sans", "font-weight":"600", "font-size": 12, "transform": "matrix(1 0 0 1 98.6264 51.0823)", "fill":"#585857"});
paper.customAttributes.txtfrivardival = function (txtfrivardival) {
return {
txtfrivardival: [txtfrivardival],
text: formatNumber(Math.floor(txtfrivardival)) + '\n'
}
}
var txtfrivardival = paper
.text(126.2,61.3)
.attr({
"font-size": 20,
"fill": "#585857",
"font-family":"Open sans",
"font-weight":"700",
txtfrivardival: [0,1000]
})
txtfrivardival.animate({
txtfrivardival: [equity, 1000]
}, 2000, "easeInOut")
};
$("#segaugeknap").click(function() {
$('#frivardihouse, #gaugebox').slideToggle(400);
if($(this).text()=== "OVERVÅGNINGSBAROMETER"){
$(this).text("TILBAGE");
document.getElementById('chart-gauge').innerHTML = '';
setTimeout(dogauge, 401);
}
else{
$(this).text("OVERVÅGNINGSBAROMETER");
document.getElementById('frivardihouse').innerHTML = '';
setTimeout(dohouse, 401);
}
});
$(document).ready(function(){
dohouse();
})
.chart-gauge {
width: 100%;
height: 180px;
margin-left: 10px;
}
.chart-color1 {
fill: rgb(200,0,0);
}
.chart-color2 {
fill: rgb(251, 183, 50);
}
.chart-color3 {
fill: rgb(89, 186, 65);;
}
.needle,
.needle-center {
fill: #464A4F;
}
.prose {
text-align: center;
font-family: sans-serif;
color: #ababab;
}
.gaugebox {display: none; border-radius: 0px 0px 5px 5px !important;margin-top: -10px !important;padding: 0px 10px 20px 10px !important;}
#segauge {background-color:#000;color:#fff;width:300px;margin: 0 auto;text-align:center;padding:10px;}
.gaugebox h4 {text-align: center;font-weight: 700;margin-bottom: 0px;}
.gaugebox .gaugetxt span:first-child(){float: left;}
.gaugebox .gaugetxt span:nth-child(2){float: right;}
.gaugetxt {width: 360px; margin: 0 auto;}
.gaugefullwrapper {
background: #fff;
border-radius: 10px;
width: 380px;
margin: 0 auto;
padding-bottom: 10px;
box-shadow: 0px 4px 15px rgba(0,0,0,0.2);
}
.gaugewrapper {margin: 0 auto; width: 350px }
div#gauge {
width: 80%;height: 180px;margin: 0 auto;
}
/*hus*/
div#frivardihouse svg {
margin: 0 auto;
display: block;
padding-top: 10px;
transition: all 0.6s cubic-bezier(.87,-.41,.19,1.44)
}
div#frivardihouse svg:hover {transform: scale(1.04);
}
div#frivardihouse {
margin-top: -20px;
}
.housevalue_f {text-align: center;padding-bottom: 10px;}
.housevalue_f a span {color: #17aec6;}
.housevalue_f a {color: #666666;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.3/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js"></script>
<div class="housegauge">
<div class="graphs house">
<div id="frivardihouse"></div>
<div class="w-btn-wrapper align_center" id="segauge"><span id="segaugeknap" class="w-btn style_solid size_medium color_primary icon_none">OVERVÅGNINGSBAROMETER</span></div>
</div>
<div class="gaugebox" id="gaugebox">
<div class="gaugefullwrapper">
<div class="gaugewrapper">
<div id="chart-gauge" class="chart-gauge"></div>
</div>
<div class="gaugetxt">
<span>Langt fra omlægning</span><span>Tæt på omlægning</span>
</div>
</div>
</div>
</div>

Related

How do i add a link to this animated button

Essentially i found this button that i wanted to add to my wixsite that links to a store. I have gotten the button animation to work and this button exists as a html element on wix. But all the button does currently is do the animation and dosent link. Could someone edit this code so after the animation plays the user will be redirected to a certain link.
I've tried looking up link code and inserting it in logical places to determine where it might work but obviously i dident find anything. And even if it did it likely would have redirected before the animation finished.
Here is the code without any of my attempts to try and fix this problem.
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function (min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function (x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function (x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function () {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
window.setTimeout(buttonEffect, 100);
loop();
window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for (key in args) {
options[key] = args[key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs);// * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
};
})();
body {
margin: 0;
overflow: hidden;
}
#myCanvas {
display: block;
}
#button {
font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
position: absolute;
font-size: 1.5em;
text-transform: uppercase;
padding: 7px 20px;
left: 50%;
width: 200px;
margin-left: -100px;
top: 50%;
border-radius: 10px;
color: white;
text-shadow: -1px -1px 1px rgba(0,0,0,0.8);
border: 5px solid transparent;
border-bottom-color: rgba(0,0,0,0.35);
background: hsla(260, 100%, 50%, 1);
cursor: pointer;
outline: 0 !important;
animation: pulse 1s infinite alternate;
transition: background 0.4s, border 0.2s, margin 0.2s;
}
#button:hover {
background: hsla(220, 100%, 60%, 1);
margin-top: -1px;
animation: none;
}
#button:active {
border-bottom-width: 0;
margin-top: 5px;
}
#keyframes pulse {
0% {
margin-top: 0px;
}
100% {
margin-top: 6px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="button">Donate</button>
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>
So again the expected result is to play the animation for the button then redirect to another page and the current result is the button simply playing the animation when clicked. If anyone could please write this code it would be super helpful.
Try changing your button to a href link. You may have to add some extra styling to the id class, but this should work.
<a id="button" href="https://www.linktosite.com">Link Button</a>
Put this on the button html tag onclick="location.href='http://www.link.com'"
You should add an activity when click on button. For example:
<button id="button" onclick="window.location.href = 'https://www.google.com';">Donate</button>
Demo:
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function (min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function (x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function (x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function () {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
window.setTimeout(buttonEffect, 100);
loop();
window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for (key in args) {
options[key] = args[key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs);// * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
};
})();
body {
margin: 0;
overflow: hidden;
}
#myCanvas {
display: block;
}
#button {
font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
position: absolute;
font-size: 1.5em;
text-transform: uppercase;
padding: 7px 20px;
left: 50%;
width: 200px;
margin-left: -100px;
top: 50%;
border-radius: 10px;
color: white;
text-shadow: -1px -1px 1px rgba(0,0,0,0.8);
border: 5px solid transparent;
border-bottom-color: rgba(0,0,0,0.35);
background: hsla(260, 100%, 50%, 1);
cursor: pointer;
outline: 0 !important;
animation: pulse 1s infinite alternate;
transition: background 0.4s, border 0.2s, margin 0.2s;
}
#button:hover {
background: hsla(220, 100%, 60%, 1);
margin-top: -1px;
animation: none;
}
#button:active {
border-bottom-width: 0;
margin-top: 5px;
}
#keyframes pulse {
0% {
margin-top: 0px;
}
100% {
margin-top: 6px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="button" onclick="window.location.href = 'https://www.google.com';">Donate</button>
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>

Why absolute positioned indicater goes out of relative positioned container?

Well I have designed a color picker, from where a selected color will show beside the canvas. Now the problem is everytime I am trying to drag the indicator it goes out of the canvas even after the position is relative.
Every time i am trying to drag the indicator it goes out of canvas. I have highlighted the indicator in the image below
var canvas = document.getElementById('color-picker');
var context = canvas.getContext('2d');
var w = 250;
var h = 250;
canvas.width = w;
canvas.height = h;
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = x;
for (var angle = 0; angle <= 360; angle += 1) {
var startAngle = (angle - 2) * Math.PI / 180;
var endAngle = angle * Math.PI / 180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, false);
context.closePath();
var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0, 'hsl(' + angle + ', 10%, 100%)');
gradient.addColorStop(1, 'hsl(' + angle + ', 100%, 50%)');
context.fillStyle = gradient;
context.fill();
}
var m = {
x: canvas.width / 2,
y: canvas.height / 2
};
var drag = false;
var location_path = document.getElementById('_lp_');
var lp_width = location_path.offsetWidth;
var lp_height = location_path.offsetHeight;
var container = document.getElementById('container');
var selected_color = document.getElementById('selected_color');
var def_color = "#f8fff9";
selected_color.style.backgroundColor = def_color;
container.addEventListener('mousedown', dragged, false);
container.addEventListener('mousemove', moving, false);
window.addEventListener('mouseup', noDrag, false);
function dragged() {
drag = true;
}
function noDrag() {
drag = false;
}
function moving(e) {
if (drag) {
var ink_x = (e.clientX - container.offsetLeft);
var ink_y = (e.clientY - container.offsetTop);
m.x = e.clientX - container.offsetLeft - lp_width / 2;
m.y = e.clientY - container.offsetTop - lp_height - 10; //why 10? 10 for padding
if (Distance(ink_x, ink_y, w / 2, h / 2) > radius) {
drag = false;
}
location_path.style.left = m.x + 'px';
location_path.style.top = m.y + 'px';
var getData = context.getImageData(ink_x, ink_y, 1, 1);
var pxl = getData.data;
var r = pxl[0];
var g = pxl[1];
var b = pxl[2];
var a = pxl[3];
// indicator.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
selected_color.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
}
}
function rgb2hex(red, green, blue) {
var rgb = blue | (green << 8) | (red << 16);
return '#' + (0x1000000 + rgb).toString(16).slice(1)
}
function Distance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
.lighting-wrapper {
margin: 5% auto;
}
.lighting-left,
.lighting-right {
padding: 50px;
}
.lighting-color-picker-wrapper,
.lighting-selected-color-wrapper {
position: relative;
width: 250px;
height: 250px;
margin: 150px auto;
border-radius: 50%;
}
.location-path {
position: absolute;
width: 40px;
height: 40px;
padding: 10px;
background: #fff;
border-radius: 50%;
border-bottom-left-radius: 0%;
top: 58px;
left: 92px;
transform: rotate(-45deg);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
user-select: none;
transition: all 0.1s;
}
<div class="container">
<div class="lighting-wrapper shadow-sm">
<div class="row align-items-center">
<div class="col-md-6 d-flex justify-content-center lighting-left">
<div class="lighting-color-picker-wrapper" id="container">
<canvas id="color-picker" class="position-relative"></canvas>
<div id="_lp_" class="location-path"></div>
</div>
</div>
<div class="col-md-6 d-flex justify-content-center lighting-right">
<div class="lighting-selected-color-wrapper" id="selected_color">
</div>
</div>
</div>
</div>
</div>
Looks like your code is affected by the page scroll.
Try change the "e.clientY" to "e.pageY".
var canvas = document.getElementById('color-picker');
var context = canvas.getContext('2d');
var w = 250;
var h = 250;
canvas.width = w;
canvas.height = h;
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = x;
for (var angle = 0; angle <= 360; angle += 1) {
var startAngle = (angle - 2) * Math.PI / 180;
var endAngle = angle * Math.PI / 180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, false);
context.closePath();
var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0, 'hsl(' + angle + ', 10%, 100%)');
gradient.addColorStop(1, 'hsl(' + angle + ', 100%, 50%)');
context.fillStyle = gradient;
context.fill();
}
var m = {
x: canvas.width / 2,
y: canvas.height / 2
};
var drag = false;
var location_path = document.getElementById('_lp_');
var lp_width = location_path.offsetWidth;
var lp_height = location_path.offsetHeight;
var container = document.getElementById('container');
var selected_color = document.getElementById('selected_color');
var def_color = "#f8fff9";
selected_color.style.backgroundColor = def_color;
container.addEventListener('mousedown', dragged, false);
container.addEventListener('mousemove', moving, false);
window.addEventListener('mouseup', noDrag, false);
function dragged() {
drag = true;
}
function noDrag() {
drag = false;
}
function moving(e) {
if (drag) {
var ink_x = (e.pageX - container.offsetLeft);
var ink_y = (e.pageY - container.offsetTop);
if (Distance(ink_x, ink_y, w / 2, h / 2) > radius) {
var vector = { x: ink_x - w / 2, y: ink_y - h / 2 };
normalize(vector);
ink_x = Math.trunc(vector.x * radius) + w / 2;
ink_y = Math.trunc(vector.y * radius) + h / 2;
drag = false;
}
m.x = ink_x - lp_width / 2;
m.y = ink_y - lp_height - 10; //why 10? 10 for padding
location_path.style.left = m.x + 'px';
location_path.style.top = m.y + 'px';
var getData = context.getImageData(ink_x, ink_y, 1, 1);
var pxl = getData.data;
var r = pxl[0];
var g = pxl[1];
var b = pxl[2];
var a = pxl[3];
// indicator.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
selected_color.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
}
}
function rgb2hex(red, green, blue) {
var rgb = blue | (green << 8) | (red << 16);
return '#' + (0x1000000 + rgb).toString(16).slice(1)
}
function Distance(x1, y1, x2, y2) {
var dx = x2 - x1;
var dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function normalize(vector) {
var length = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2));
vector.x = vector.x / length;
vector.y = vector.y / length;
}
.lighting-wrapper {
margin: 5% auto;
}
.lighting-left,
.lighting-right {
padding: 50px;
}
.lighting-color-picker-wrapper,
.lighting-selected-color-wrapper {
position: relative;
width: 250px;
height: 250px;
margin: 150px auto;
border-radius: 50%;
}
.location-path {
position: absolute;
width: 40px;
height: 40px;
padding: 10px;
background: #fff;
border-radius: 50%;
border-bottom-left-radius: 0%;
top: 58px;
left: 92px;
transform: rotate(-45deg);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
user-select: none;
transition: all 0.1s;
}
<div class="container">
<div class="lighting-wrapper shadow-sm">
<div class="row align-items-center">
<div class="col-md-6 d-flex justify-content-center lighting-left">
<div class="lighting-color-picker-wrapper" id="container">
<canvas id="color-picker" class="position-relative"></canvas>
<div id="_lp_" class="location-path"></div>
</div>
</div>
<div class="col-md-6 d-flex justify-content-center lighting-right">
<div class="lighting-selected-color-wrapper" id="selected_color">
</div>
</div>
</div>
</div>
</div>

HTML h1 tag not displaying correctly above javascript+css animation

I have the following code (from a code pen fork), and wish to add a simple Html H1 tag above the animation on the page. I have tried the below, but for some reason the H1 tag just displays for a second (flashes) and then disappears off the screen.
I have tried placing it in several places and also used tags, but the same thing happens.
Can someone please suggest a fix and also explain why this is occuring?
html, javascript file: and CSS File (style.css)
class Canvas {
constructor(element, ctx, w, h) {
this.element = element
this.ctx = ctx
this.width = w
this.height = h
this.interactive = false
this.playing = true
this.point = {
value: 150,
speed: 0.25,
limit: 70,
floor: 10,
up: true,
animating: false
}
this.multiplier = {
value: 1,
speed: 0.005,
limit: 20,
floor: 1,
up: true,
animating: true
}
this.center = {
x: w / 2,
y: h / 2,
targetX: w / 2,
targetY: h / 2,
easing: 0.02
}
this.radius = {
val: h / 2.2,
targetVal: h / 2.2,
easing: 0.02
}
document.body.addEventListener('click', this.click.bind(this))
document.body.addEventListener('mousemove', this.move.bind(this))
document.body.addEventListener('keyup', this.keyup.bind(this))
this.hue = 160
}
click(e) {
this.interactive = !this.interactive
if (!this.interactive) {
this.center.targetX = this.width / 2
this.center.targetY = this.height / 2
this.radius.targetVal = this.height / 2.2
this.element.classList.remove('interactive')
} else {
this.element.classList.add('interactive')
}
}
move(e) {
if (!this.interactive) {
return
}
const h3 = this.height / 3
this.center.targetX = e.pageX
this.center.targetY = Math.max(e.pageY, h3)
this.radius.targetVal = h3 + (e.pageY * 0.8)
}
keyup(e) {
if (e.which != 32) {
return
}
this.playing = !this.playing
if (this.playing && this.drawLoop) {
this.drawLoop()
}
}
update() {
this.clear()
this.animate(this.point)
this.animate(this.multiplier)
this.ease(this.center)
this.ease(this.radius)
this.hue += 0.3
const h = (this.hue % 360)
this.ctx.fillStyle = 'hsl(' + h + ',70%,20%)'
this.ctx.strokeStyle = 'hsla(' + h + ',80%,60%,0.2)'
this.ctx.globalCompositeOperation = 'lighter'
}
clear() {
this.ctx.globalCompositeOperation = 'source-over'
this.ctx.fillStyle = 'rgba(0,0,0,0.1)'
this.ctx.rect(0, 0, this.width, this.height)
this.ctx.fill()
}
draw() {
let radius = this.radius.val
const w2 = this.center.x,
h2 = this.center.y
this.ctx.beginPath()
this.ctx.shadowBlur = 0
this.ctx.shadowColor = 'black'
const points = this.point.value
const multiplier = this.multiplier.value
for (let p = 0; p < points; p++) {
const t = (p / points) * Math.PI * 2
const t2 = ((p * multiplier) / points) * Math.PI * 2
const x = radius * Math.cos(t) + w2
const y = radius * Math.sin(t) + h2
const x2 = radius * Math.cos(t2) + w2
const y2 = radius * Math.sin(t2) + h2
this.ctx.moveTo(x, y)
this.ctx.lineTo(x2, y2)
}
this.ctx.arc(w2, h2, radius, 0, 2 * Math.PI)
this.ctx.stroke()
this.ctx.closePath()
}
animate(object) {
if (!object.animating) {
return
}
if (object.up) {
object.value += object.speed
} else {
object.value -= object.speed
}
if (object.value > object.limit) {
object.up = false
} else if (object.value < object.floor) {
object.up = true
}
}
ease(object) {
if (object.val) {
const dv = object.targetVal - object.val
object.val += dv * object.easing
return
}
const dx = object.targetX - object.x
const dy = object.targetY - object.y
object.x += dx * object.easing
object.y += dy * object.easing
}
random(from, to) {
return from + (Math.rand() * (to - from))
}
resize(w, h) {
this.width = w
this.height = h
this.center.targetX = w / 2
this.center.targetY = h / 2
this.radius.targetVal = h / 2.2
}
}
(_ => {
const canvasElement = document.getElementById('canvas'),
ctx = canvasElement.getContext('2d')
let w = canvasElement.width = window.innerWidth,
h = canvasElement.height = window.innerHeight,
density = 1
const canvas = new Canvas(canvasElement, ctx, w, h)
function setup() {
window.addEventListener('resize', resize)
density = window.devicePixelRatio != undefined ? window.devicePixelRatio : 1.0
canvasElement.width = w * density
canvasElement.height = h * density
canvas.width = w
canvas.height = h
canvas.drawLoop = draw
ctx.scale(density, density)
draw()
}
function draw() {
canvas.update()
canvas.draw()
if (canvas.playing) {
window.requestAnimationFrame(draw)
}
}
function resize() {
w = canvasElement.width = window.innerWidth
h = canvasElement.height = window.innerHeight
canvasElement.width = w * density
canvasElement.height = h * density
canvas.resize(w, h)
ctx.scale(density, density)
}
setup()
})()
body {
background: #000;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
canvas.interactive {
cursor: none;
}
<html>
<head>
<link rel="stylesheet" href="style.css">
<center>
<h1>
<font color="white">This is the H1 Tag</font>
</h1>
</center>
</head>
<body>
<br>
<br>
<br>
<br>
<canvas id="canvas"></canvas>
Update
Thanks to the answer below, I have changed the css to the following, and the tag does display, but the animation is not centered. How can the canvas be re-positioned so that other 'elements' or objects can be fit around it?
canvas {
width: 30%;
height: 30%;
position: absolute;
left: 0;
top: 0;
}
This is because your canvas style is set to take up the whole page. Your h1 is also inside the head of the document. So that needs moved into the body too.
canvas {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
If you remove the canvas style, your h1 will sit above the canvas.
Edit:
Reading between the lines OP wants the image scaled down and centered. I've created a Fiddle to show how this can be achieved.
Fiddle
Add some z-index to your h1 and remove the obsolete tags:
class Canvas {
constructor(element, ctx, w, h) {
this.element = element
this.ctx = ctx
this.width = w
this.height = h
this.interactive = false
this.playing = true
this.point = {
value: 150,
speed: 0.25,
limit: 70,
floor: 10,
up: true,
animating: false
}
this.multiplier = {
value: 1,
speed: 0.005,
limit: 20,
floor: 1,
up: true,
animating: true
}
this.center = {
x: w / 2,
y: h / 2,
targetX: w / 2,
targetY: h / 2,
easing: 0.02
}
this.radius = {
val: h / 2.2,
targetVal: h / 2.2,
easing: 0.02
}
document.body.addEventListener('click', this.click.bind(this))
document.body.addEventListener('mousemove', this.move.bind(this))
document.body.addEventListener('keyup', this.keyup.bind(this))
this.hue = 160
}
click(e) {
this.interactive = !this.interactive
if (!this.interactive) {
this.center.targetX = this.width / 2
this.center.targetY = this.height / 2
this.radius.targetVal = this.height / 2.2
this.element.classList.remove('interactive')
} else {
this.element.classList.add('interactive')
}
}
move(e) {
if (!this.interactive) {
return
}
const h3 = this.height / 3
this.center.targetX = e.pageX
this.center.targetY = Math.max(e.pageY, h3)
this.radius.targetVal = h3 + (e.pageY * 0.8)
}
keyup(e) {
if (e.which != 32) {
return
}
this.playing = !this.playing
if (this.playing && this.drawLoop) {
this.drawLoop()
}
}
update() {
this.clear()
this.animate(this.point)
this.animate(this.multiplier)
this.ease(this.center)
this.ease(this.radius)
this.hue += 0.3
const h = (this.hue % 360)
this.ctx.fillStyle = 'hsl(' + h + ',70%,20%)'
this.ctx.strokeStyle = 'hsla(' + h + ',80%,60%,0.2)'
this.ctx.globalCompositeOperation = 'lighter'
}
clear() {
this.ctx.globalCompositeOperation = 'source-over'
this.ctx.fillStyle = 'rgba(0,0,0,0.1)'
this.ctx.rect(0, 0, this.width, this.height)
this.ctx.fill()
}
draw() {
let radius = this.radius.val
const w2 = this.center.x,
h2 = this.center.y
this.ctx.beginPath()
this.ctx.shadowBlur = 0
this.ctx.shadowColor = 'black'
const points = this.point.value
const multiplier = this.multiplier.value
for (let p = 0; p < points; p++) {
const t = (p / points) * Math.PI * 2
const t2 = ((p * multiplier) / points) * Math.PI * 2
const x = radius * Math.cos(t) + w2
const y = radius * Math.sin(t) + h2
const x2 = radius * Math.cos(t2) + w2
const y2 = radius * Math.sin(t2) + h2
this.ctx.moveTo(x, y)
this.ctx.lineTo(x2, y2)
}
this.ctx.arc(w2, h2, radius, 0, 2 * Math.PI)
this.ctx.stroke()
this.ctx.closePath()
}
animate(object) {
if (!object.animating) {
return
}
if (object.up) {
object.value += object.speed
} else {
object.value -= object.speed
}
if (object.value > object.limit) {
object.up = false
} else if (object.value < object.floor) {
object.up = true
}
}
ease(object) {
if (object.val) {
const dv = object.targetVal - object.val
object.val += dv * object.easing
return
}
const dx = object.targetX - object.x
const dy = object.targetY - object.y
object.x += dx * object.easing
object.y += dy * object.easing
}
random(from, to) {
return from + (Math.rand() * (to - from))
}
resize(w, h) {
this.width = w
this.height = h
this.center.targetX = w / 2
this.center.targetY = h / 2
this.radius.targetVal = h / 2.2
}
}
(_ => {
const canvasElement = document.getElementById('canvas'),
ctx = canvasElement.getContext('2d')
let w = canvasElement.width = window.innerWidth,
h = canvasElement.height = window.innerHeight,
density = 1
const canvas = new Canvas(canvasElement, ctx, w, h)
function setup() {
window.addEventListener('resize', resize)
density = window.devicePixelRatio != undefined ? window.devicePixelRatio : 1.0
canvasElement.width = w * density
canvasElement.height = h * density
canvas.width = w
canvas.height = h
canvas.drawLoop = draw
ctx.scale(density, density)
draw()
}
function draw() {
canvas.update()
canvas.draw()
if (canvas.playing) {
window.requestAnimationFrame(draw)
}
}
function resize() {
w = canvasElement.width = window.innerWidth
h = canvasElement.height = window.innerHeight
canvasElement.width = w * density
canvasElement.height = h * density
canvas.resize(w, h)
ctx.scale(density, density)
}
setup()
})()
body {
background: #000;
overflow: hidden;
}
h1 {
position:relative;
z-index:2;
color:#fff;
text-align:center;
}
canvas {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
canvas.interactive {
cursor: none;
}
<canvas id="canvas"></canvas>
<h1>This is a title</h1>
This is because of your canvas styles. If you add a margin-top to your canvas the h1 will not be removed, try it like this:
canvas {
margin-top: 200px;
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
You'll see that now your h1 is not dissapearing anymore.
Edit
Reading between the lines OP appears to want it scaled down and centered, so I've created a fiddle with updated code.
Fiddle

Javascript glitch effect, text is too big, how do I resize?

I've used some code from a Pen I found online to produce a glitch text effect. However, the text is too big for the page, and I don't understand how I can change it.
Here is how the text displays:
too big
Here is how I want it to display:
how I'd like it
Here is the html:
<div class="glitch">
<div id="wrapper">
<canvas id="stage"></canvas>
Css:
.glitch {
background: black;
overflow: hidden;
margin: 0;
padding: 0;
width: 100%;
}
#wrapper {
width: 100%;
padding: 0;
margin: 0 auto;
max-width: 100%;
/*overflow: hidden;*/
text-align: center;
}
img {
display: none;
}
canvas {
box-sizing: border-box;
padding: 0 40px 0 0;
margin: 20px auto 0;
text-align: center;
max-width: 100%;
}
JS:
(function (){
"use strict";
var textSize = 10;
var glitcher = {
init: function () {
setTimeout((function () {
this.canvas = document.getElementById('stage');
this.context = this.canvas.getContext('2d');
this.initOptions();
this.resize();
this.tick();
}).bind(this), 100);
},
initOptions: function () {
var gui = new dat.GUI(),
current = gui.addFolder('Current'),
controls = gui.addFolder('Controls');
this.width = document.documentElement.offsetWidth;
this.height = document.documentElement.offsetHeight;
this.textSize = Math.floor(this.width / 7);
// sets text size based on window size
if (this.textSize > this.height) {
this.textSize = Math.floor(this.height/1.5); }
// tries to make text fit if window is
// very wide, but not very tall
this.font = '900 ' + this.textSize + 'px "Josefin Sans"';
this.context.font = this.font;
this.text = "ROYAL ARCADE";
this.textWidth = (this.context.measureText(this.text)).width;
this.fps = 60;
this.channel = 0; // 0 = red, 1 = green, 2 = blue
this.compOp = 'lighter'; // CompositeOperation = lighter || darker || xor
this.phase = 0.0;
this.phaseStep = 0.05; //determines how often we will change channel and amplitude
this.amplitude = 0.0;
this.amplitudeBase = 2.0;
this.amplitudeRange = 2.0;
this.alphaMin = 0.8;
this.glitchAmplitude = 20.0;
this.glitchThreshold = 0.9;
this.scanlineBase = 40;
this.scanlineRange = 40;
this.scanlineShift = 15;
current.add(this, 'channel', 0, 2).listen();
current.add(this, 'phase', 0, 1).listen();
current.add(this, 'amplitude', 0, 5).listen();
// comment out below to hide ability to change text string
var text = controls.add(this, 'text');
text.onChange((function (){
this.textWidth = (this.context.measureText(this.text)).width;
}).bind(this));
// comment out above to hide ability to change text string
controls.add(this, 'fps', 1, 60);
controls.add(this, 'phaseStep', 0, 1);
controls.add(this, 'alphaMin', 0, 1);
controls.add(this, 'amplitudeBase', 0, 5);
controls.add(this, 'amplitudeRange', 0, 5);
controls.add(this, 'glitchAmplitude', 0, 100);
controls.add(this, 'glitchThreshold', 0, 1);
controls.open();
gui.close(); // start the control panel cloased
},
tick: function () {
setTimeout((function () {
this.phase += this.phaseStep;
if (this.phase > 1) {
this.phase = 0.0;
this.channel = (this.channel === 2) ? 0 : this.channel + 1;
this.amplitude = this.amplitudeBase + (this.amplitudeRange * Math.random());
}
this.render();
this.tick();
}).bind(this), 1000 / this.fps);
},
render: function () {
var x0 = this.amplitude * Math.sin((Math.PI * 2) * this.phase) >> 0,
x1, x2, x3;
if (Math.random() >= this.glitchThreshold) {
x0 *= this.glitchAmplitude;
}
x1 = this.width - this.textWidth >> 1;
x2 = x1 + x0;
x3 = x1 - x0;
this.context.clearRect(0, 0, this.width, this.height);
this.context.globalAlpha = this.alphaMin + ((1 - this.alphaMin) * Math.random());
switch (this.channel) {
case 0:
this.renderChannels(x1, x2, x3);
break;
case 1:
this.renderChannels(x2, x3, x1);
break;
case 2:
this.renderChannels(x3, x1, x2);
break;
}
this.renderScanline();
if (Math.floor(Math.random() * 2) > 1) {
this.renderScanline();
// renders a second scanline 50% of the time
}
},
renderChannels: function (x1, x2, x3) {
this.context.font = this.font;
this.context.fillStyle = "rgb(255,0,0)";
this.context.fillText(this.text, x1, this.height / 2);
this.context.globalCompositeOperation = this.compOp;
this.context.fillStyle = "rgb(0,255,0)";
this.context.fillText(this.text, x2, this.height / 2);
this.context.fillStyle = "rgb(0,0,255)";
this.context.fillText(this.text, x3, this.height / 2);
},
renderScanline: function () {
var y = this.height * Math.random() >> 0,
o = this.context.getImageData(0, y, this.width, 1),
d = o.data,
i = d.length,
s = this.scanlineBase + this.scanlineRange * Math.random() >> 0,
x = -this.scanlineShift + this.scanlineShift * 2 * Math.random() >> 0;
while (i-- > 0) {
d[i] += s;
}
this.context.putImageData(o, x, y);
},
resize: function () {
this.width = document.documentElement.offsetWidth;
//this.height = window.innerHeight;
this.height = document.documentElement.offsetHeight;
if (this.canvas) {
this.canvas.height = this.height;
//document.documentElement.offsetHeight;
this.canvas.width = this.width;
//document.documentElement.offsetWidth;
this.textSize = Math.floor(this.canvas.width / 7);
// RE-sets text size based on window size
if (this.textSize > this.height) {
this.textSize = Math.floor(this.canvas.height/1.5); }
// tries to make text fit if window is
// very wide, but not very tall
this.font = '900 ' + this.textSize + 'px "Josefin Sans"';
this.context.font = this.font;
}
}
};
document.onload = glitcher.init();
window.onresize = glitcher.resize();
// return;
// executes anonymous function onload
})();
Thanks to anyone who can help me
I couldn't figure it out but here's an example of the glitch effect and the problem. Maybe someone can see what's going on here.
(function() {
"use strict";
var textSize = 10;
var glitcher = {
init: function() {
setTimeout((function() {
this.canvas = document.getElementById('stage');
this.context = this.canvas.getContext('2d');
this.initOptions();
this.resize();
this.tick();
}).bind(this), 100);
},
initOptions: function() {
var gui = new dat.GUI(),
current = gui.addFolder('Current'),
controls = gui.addFolder('Controls');
this.width = document.documentElement.offsetWidth;
this.height = document.documentElement.offsetHeight;
this.textSize = Math.floor(this.width / 7);
// sets text size based on window size
if (this.textSize > this.height) {
this.textSize = Math.floor(this.height / 1.5);
}
// tries to make text fit if window is
// very wide, but not very tall
this.font = '900 ' + this.textSize + 'px "Josefin Sans"';
this.context.font = this.font;
this.text = "ROYAL ARCADE";
this.textWidth = (this.context.measureText(this.text)).width;
this.fps = 60;
this.channel = 0; // 0 = red, 1 = green, 2 = blue
this.compOp = 'lighter'; // CompositeOperation = lighter || darker || xor
this.phase = 0.0;
this.phaseStep = 0.05; //determines how often we will change channel and amplitude
this.amplitude = 0.0;
this.amplitudeBase = 2.0;
this.amplitudeRange = 2.0;
this.alphaMin = 0.8;
this.glitchAmplitude = 20.0;
this.glitchThreshold = 0.9;
this.scanlineBase = 40;
this.scanlineRange = 40;
this.scanlineShift = 15;
current.add(this, 'channel', 0, 2).listen();
current.add(this, 'phase', 0, 1).listen();
current.add(this, 'amplitude', 0, 5).listen();
// comment out below to hide ability to change text string
var text = controls.add(this, 'text');
text.onChange((function() {
this.textWidth = (this.context.measureText(this.text)).width;
}).bind(this));
// comment out above to hide ability to change text string
controls.add(this, 'fps', 1, 60);
controls.add(this, 'phaseStep', 0, 1);
controls.add(this, 'alphaMin', 0, 1);
controls.add(this, 'amplitudeBase', 0, 5);
controls.add(this, 'amplitudeRange', 0, 5);
controls.add(this, 'glitchAmplitude', 0, 100);
controls.add(this, 'glitchThreshold', 0, 1);
controls.open();
gui.close(); // start the control panel cloased
},
tick: function() {
setTimeout((function() {
this.phase += this.phaseStep;
if (this.phase > 1) {
this.phase = 0.0;
this.channel = (this.channel === 2) ? 0 : this.channel + 1;
this.amplitude = this.amplitudeBase + (this.amplitudeRange * Math.random());
}
this.render();
this.tick();
}).bind(this), 1000 / this.fps);
},
render: function() {
var x0 = this.amplitude * Math.sin((Math.PI * 2) * this.phase) >> 0,
x1, x2, x3;
if (Math.random() >= this.glitchThreshold) {
x0 *= this.glitchAmplitude;
}
x1 = this.width - this.textWidth >> 1;
x2 = x1 + x0;
x3 = x1 - x0;
this.context.clearRect(0, 0, this.width, this.height);
this.context.globalAlpha = this.alphaMin + ((1 - this.alphaMin) * Math.random());
switch (this.channel) {
case 0:
this.renderChannels(x1, x2, x3);
break;
case 1:
this.renderChannels(x2, x3, x1);
break;
case 2:
this.renderChannels(x3, x1, x2);
break;
}
this.renderScanline();
if (Math.floor(Math.random() * 2) > 1) {
this.renderScanline();
// renders a second scanline 50% of the time
}
},
renderChannels: function(x1, x2, x3) {
this.context.font = this.font;
this.context.fillStyle = "rgb(255,0,0)";
this.context.fillText(this.text, x1, this.height / 2);
this.context.globalCompositeOperation = this.compOp;
this.context.fillStyle = "rgb(0,255,0)";
this.context.fillText(this.text, x2, this.height / 2);
this.context.fillStyle = "rgb(0,0,255)";
this.context.fillText(this.text, x3, this.height / 2);
},
renderScanline: function() {
var y = this.height * Math.random() >> 0,
o = this.context.getImageData(0, y, this.width, 1),
d = o.data,
i = d.length,
s = this.scanlineBase + this.scanlineRange * Math.random() >> 0,
x = -this.scanlineShift + this.scanlineShift * 2 * Math.random() >> 0;
while (i-- > 0) {
d[i] += s;
}
this.context.putImageData(o, x, y);
},
resize: function() {
this.width = document.documentElement.offsetWidth;
//this.height = window.innerHeight;
this.height = document.documentElement.offsetHeight;
if (this.canvas) {
this.canvas.height = this.height;
//document.documentElement.offsetHeight;
this.canvas.width = this.width;
//document.documentElement.offsetWidth;
this.textSize = Math.floor(this.canvas.width / 7);
// RE-sets text size based on window size
if (this.textSize > this.height) {
this.textSize = Math.floor(this.canvas.height / 1.5);
}
// tries to make text fit if window is
// very wide, but not very tall
this.font = '900 ' + this.textSize + 'px "Josefin Sans"';
this.context.font = this.font;
}
}
};
//document.onload = glitcher.init;
glitcher.init();
window.onresize = glitcher.resize;
// return;
// executes anonymous function onload
})();
.glitch {
background: black;
overflow: hidden;
margin: 0;
padding: 0;
width: 100%;
}
#wrapper {
width: 100%;
padding: 0;
margin: 0 auto;
max-width: 100%;
/*overflow: hidden;*/
text-align: center;
}
img {
display: none;
}
canvas {
box-sizing: border-box;
padding: 0 40px 0 0;
margin: 20px auto 0;
text-align: center;
max-width: 100%;
}
<script type="text/javascript" src="https://raw.githubusercontent.com/dataarts/dat.gui/master/build/dat.gui.js"></script>
<div class="glitch">
<div id="wrapper">
<canvas id="stage"></canvas>
</div>
</div>

Animated SVG circles (timer and progress)

How can I change this:
var el = document.getElementById('graph'); // get canvas
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
div {
position:relative;
margin:80px;
width:220px; height:220px;
}
canvas {
display: block;
position:absolute;
top:0;
left:0;
}
span {
color:#555;
display:block;
line-height:220px;
text-align:center;
width:220px;
font-family:sans-serif;
font-size:40px;
font-weight:100;
margin-left:5px;
}
input {
width: 200px;
}
<div class="chart" id="graph" data-percent="10"></div>
To get this:
outer circle is just a progress from 0 to 100%
inner - timer
I did this
but through the ass
http://codepen.io/di3orlive/pen/wKjBzY
I would like to do it more nicer
and with an arrow
var el = document.getElementById('graph'); // get canvas
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 4,
rotate: el.getAttribute('data-rotate') || 0
}
function Gauge() {
this.to_rad = to_rad = Math.PI / 180;
this.percentBg = "#efefef";
this.percentFg = "#555555";
this.tickFg = "#cccccc";
this.tickBg = "transparent";
this.tickFill = true;
this.tickDirection = -1; // 1=clockwise, -1=counterclockewise
this.percent = 0;
this.size = 220;
this.lineWidth = 14;
this.rotate = 0;
this.ticks = 40;
this.tick = 0;
this.can = document.createElement('canvas');
this.ctx = this.can.getContext('2d');
}
Gauge.prototype.drawCircle = function(color, lineWidth, percent, drawArrow) {
var ctx = this.ctx;
var circleMargin = 10; // need room for arrowhead
var radius = (this.size - this.lineWidth - circleMargin) / 2;
ctx.save();
var mid = this.size / 2;
ctx.translate(mid, mid);
ctx.rotate(-90 * to_rad);
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
var endRadians = 360 * percent * this.to_rad;
ctx.arc(0, 0, radius, 0, endRadians, false);
ctx.strokeStyle = ctx.filStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
if (drawArrow === true && percent !== 1) {
ctx.beginPath();
ctx.rotate(endRadians);
var arrowWidth = this.lineWidth + 12;
var arrowHeight = 10;
ctx.moveTo(radius - (arrowWidth / 2), 0);
ctx.lineTo(radius + (arrowWidth / 2), 0);
ctx.lineTo(radius, arrowHeight);
ctx.fill();
}
ctx.restore();
};
Gauge.prototype.drawTicks = function() {
var circleMargin = 10; // need room for arrowhead
var radius = (this.size - this.lineWidth - circleMargin) / 2;
var ctx = this.ctx;
ctx.save();
var mid = this.size / 2;
ctx.translate(mid, mid);
ctx.rotate(-90 * to_rad);
ctx.lineWidth = 3;
var angle = 360 / this.ticks;
var tickSize = 20;
var tickMargin = 10;
for (var i = 0; i < this.ticks; i++) {
if ((i < this.tick && this.tickFill == true) || i == this.tick) {
ctx.strokeStyle = this.tickFg;
} else {
ctx.strokeStyle = this.tickBg;
}
ctx.save();
if (this.tickDirection === -1) {
ctx.rotate((360 - (i * angle)) * this.to_rad);
} else {
ctx.rotate(i * angle * this.to_rad);
}
ctx.beginPath();
ctx.moveTo(radius - tickSize - tickMargin, 0);
ctx.lineTo(radius - tickMargin, 0);
ctx.stroke();
ctx.restore();
}
ctx.restore();
};
Gauge.prototype.render = function(el) {
this.can.width = this.can.height = this.size;
this.span = document.createElement('span');
el.innerHTML = "";
el.appendChild(this.can);
el.appendChild(this.span);
var self = this;
var ctx = self.ctx;
function loop() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
self.drawCircle(self.percentBg, self.lineWidth, 100 / 100);
self.drawCircle(self.percentFg, self.lineWidth, self.percent / 100, true);
self.drawTicks();
self.timeout = setTimeout(function() {
loop()
}, 1000 / 30);
}
loop();
}
var myGauge = new Gauge();
myGauge.size = options.size;
myGauge.percent = options.percent;
myGauge.lineWidth = options.lineWidth;
myGauge.percent = options.percent;
myGauge.render(el)
var myGauge2 = new Gauge();
myGauge2.size = options.size;
myGauge2.percent = options.percent;
myGauge2.lineWidth = options.lineWidth;
myGauge2.percent = options.percent;
myGauge2.tickFg = "#FF8800";
myGauge2.tickBg = "#EEEEEE";
myGauge2.tickFill = false;
myGauge2.ticks = 60;
myGauge2.tickDirection = 1;
myGauge2.render(document.getElementById('gauge'));
var startTime = (new Date()).getTime();
var countDown = 99;
function dataLoop() {
myGauge.percent = myGauge.percent > 100 ? 100 : (myGauge.percent * 1) + .1;
var elapsedMs = (new Date().getTime()) - startTime; // milliseconds;
var elapsedSec = elapsedMs / 1000;
var remainSec = Math.floor(countDown - elapsedSec);
var progress = remainSec <=0 ? 1 : elapsedSec / countDown;
myGauge.tick = Math.floor(progress * myGauge.ticks);
myGauge.span.innerHTML = remainSec > 0 ? remainSec + " sec" : "---";
var d = new Date();
myGauge2.percent = (d.getMinutes() / 60) * 100;
if (myGauge2.percent > 100) myGauge2.percent = 100;
myGauge2.tick = d.getSeconds();
myGauge2.span.innerHTML = d.getSeconds() + " sec";
setTimeout(dataLoop,1000/30);
}
dataLoop();
div {
position: relative;
margin: 80px;
width: 220px;
height: 220px;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
span {
color: #555;
display: block;
line-height: 220px;
text-align: center;
width: 100%;
font-family: sans-serif;
font-size: 40px;
font-weight: 100;
margin-left: 5px;
}
input {
width: 200px;
}
<table>
<tr>
<td>
<div class="chart" id="graph" data-percent="10"></div>
</td>
<td>
<div id="gauge"></div>
</td>
</tr>
</table>

Categories

Resources