How to link audio file and autoplay - javascript

I have an audio visualizer that creates audio waves based on the inputed music file. The file has to manually be put into the "choose file" area. How do I make it so that I can simply link a pr-existing file, so that when the page loads, it immediately starts playing audio.mp3
Here is the code that Im working with:
window.onload = function() {
var audio,
analyser,
audioContext,
sourceNode,
stream;
var svg = document.getElementById('svg'),
svgNS = svg.namespaceURI,
g = document.createElementNS(svgNS, "g");
var width = window.innerWidth,
height = window.innerHeight,
maxHeight = Math.max(height * 0.3, 300),
fftSize = 512, // 512
tilt = 40,
choke = 110,
c = 0;
var audioInput = document.getElementById('audiofile');
// choose file
audioInput.addEventListener('change', function(event) {
stream = URL.createObjectURL(event.target.files[0]);
audio = new Audio();
audio.src = stream;
setup();
});
function setup() {
audio.addEventListener('canplay', function () {
document.body.className+='loaded';
audioContext = new AudioContext();
analyser = (analyser || audioContext.createAnalyser());
analyser.minDecibels = -90;
analyser.maxDecibels = -10;
analyser.smoothingTimeConstant = 1;//0.75;
analyser.fftSize = fftSize;
sourceNode = audioContext.createMediaElementSource(audio);
sourceNode.connect(analyser);
sourceNode.connect(audioContext.destination);
audio.play();
update();
});
}
function shape(g, freqValue, freqSequence, freqCount, colorSequence) {
var freqRatio = freqSequence/freqCount,
x = (width - (tilt * 2)) * freqRatio + tilt,
y = height / 2;
var polyline = document.createElementNS(svgNS, "polyline"),
// using power to increase highs and decrease lows
freqRatio = freqValue / 255,
throttledRatio = (freqValue - choke) / (255 - choke),
strokeWidth = width / freqCount * 0.6 * throttledRatio,
throttledY = Math.max(throttledRatio, 0) * maxHeight,
// color
color = "hsl(" +
((freqSequence / 2) + Math.floor(colorSequence)) + ", " +
100 + "%," +
freqRatio * 80 + "%" +
")";
var loc_x = x - strokeWidth / 2,
loc_y1 = y - throttledY / 2,
loc_y2 = y + throttledY / 2,
x_offset = tilt * throttledRatio;
if (throttledRatio > 0) {
var point_1 = (loc_x - x_offset) + "," + loc_y1,
point_2 = (loc_x + x_offset) + "," + loc_y2;
var points = [ point_1, point_2 ];
} else {
var points = [loc_x + "," + (y-1),loc_x + "," + (y+1)]
}
polyline.setAttribute("stroke-width", strokeWidth);
polyline.setAttribute("stroke", color);
polyline.setAttribute("points", points.join(" "));
g.appendChild(polyline);
}
svg.setAttribute("width", width+"px");
svg.setAttribute("height", height+"px");
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
svg.appendChild(g);
function update() {
g.remove();
g = document.createElementNS(svgNS, "g");
var freqArray = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(freqArray);
for (var i = 0; i < freqArray.length; i++) {
var v = freqArray[i];
shape(g, v, i+1, freqArray.length, c);
}
svg.appendChild(g);
c += 0.5;
requestAnimationFrame(update);
}
};
jakealbaughSignature("light");
body {
margin: 0;
background-color: #000000;
font-family: 'Helvetica', sans-serif;
color: #FFFFFF;
}
input {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
z-index: 2;
}
body.loaded input {
display: none;
}
#svg {
display: block;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
}
#svg polyline {
stroke-linecap: round;
}
<input id=audiofile type=file>
<svg id=svg></svg>

You can't.
Autoplay of audio is disabled on most browsers. There must be some user interaction, and you can only start playback on that user interaction, such as a click event.

Related

Cannot read properties of null (reading 'animate') error chrome JS animation

I am new to webdev and I am trying to use this CodePen to animate my buttons:
https://codepen.io/Mamboleoo/pen/JjdXPgR
However, I am still getting this error on chrome when trying to run the code:
Uncaught TypeError: Cannot read properties of null (reading 'animate')
I tried replacing the last JS line to: if ( document.getElementByID("aaa").animate ){} but no success.enter code here
Can anyone help me please ?
HTML
<div class="contianer">
<div class="wrapper" id="aaa">
<button data-type="square">Square particles</button>
<button data-type="emoji">Emoji particles</button>
<button data-type="mario">Mario particles</button>
<button data-type="shadow">Shadow particles</button>
<button data-type="line">Line particles</button>
</div>
<span class="preloader"></span>
</div>
CSS
particle {
position: fixed;
top: 0;
left: 0;
opacity: 0;
pointer-events: none;
background-repeat: no-repeat;
background-size: contain;
}
.wrapper {
position: absolute;
}
.wrapper button {
padding: 20px;
margin: 10px;
align-self: center;
}
.preloader {
position: absolute;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/mario-face.png);
}
JS:
function pop (e) {
let amount = 30;
switch (e.target.dataset.type) {
case 'shadow':
case 'line':
amount = 60;
break;
}
// Quick check if user clicked the button using a keyboard
if (e.clientX === 0 && e.clientY === 0) {
const bbox = e.target.getBoundingClientRect();
const x = bbox.left + bbox.width / 2;
const y = bbox.top + bbox.height / 2;
for (let i = 0; i < 30; i++) {
// We call the function createParticle 30 times
// We pass the coordinates of the button for x & y values
createParticle(x, y, e.target.dataset.type);
}
} else {
for (let i = 0; i < amount; i++) {
createParticle(e.clientX, e.clientY + window.scrollY, e.target.dataset.type);
}
}
}
function createParticle (x, y, type) {
const particle = document.createElement('particle');
document.body.appendChild(particle);
let width = Math.floor(Math.random() * 30 + 8);
let height = width;
let destinationX = (Math.random() - 0.5) * 300;
let destinationY = (Math.random() - 0.5) * 300;
let rotation = Math.random() * 520;
let delay = Math.random() * 200;
switch (type) {
case 'square':
particle.style.background = `hsl(${Math.random() * 90 + 270}, 70%, 60%)`;
particle.style.border = '1px solid white';
break;
case 'emoji':
particle.innerHTML = ['❤','🧡','💛','💚','💙','💜','🤎'][Math.floor(Math.random() * 7)];
particle.style.fontSize = `${Math.random() * 24 + 10}px`;
width = height = 'auto';
break;
case 'mario':
particle.style.backgroundImage = 'url(https://s3-us-west-
2.amazonaws.com/s.cdpn.io/127738/mario-face.png)';
break;
case 'shadow':
var color = `hsl(${Math.random() * 90 + 90}, 70%, 50%)`;
particle.style.boxShadow = `0 0 ${Math.floor(Math.random() * 10 + 10)}px ${color}`;
particle.style.background = color;
particle.style.borderRadius = '50%';
width = height = Math.random() * 5 + 4;
break;
case 'line':
var color = `hsl(${Math.random() * 90 + 90}, 70%, 50%)`;
particle.style.background = 'black';
height = 1;
rotation += 1000;
delay = Math.random() * 1000;
break;
}
particle.style.width = `${width}px`;
particle.style.height = `${height}px`;
const animation = particle.animate([
{
transform: `translate(-50%, -50%) translate(${x}px, ${y}px) rotate(0deg)`,
opacity: 1
},
{
transform: `translate(-50%, -50%) translate(${x + destinationX}px, ${y + destinationY}px)
rotate(${rotation}deg)`,
opacity: 0
}
], {
duration: Math.random() * 1000 + 5000,
easing: 'cubic-bezier(0, .9, .57, 1)',
delay: delay
});
animation.onfinish = removeParticle;
}
function removeParticle (e) {
e.srcElement.effect.target.remove();
}
if (document.body.animate) {
document.querySelectorAll('button').forEach(button => button.addEventListener('click', pop));
}

How to rotate point and place in the center?

I have tried to rotate point in case when parent container was rotated:
https://stackblitz.com/edit/js-qzfdbb?file=index.js
Code is:
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
let leftTopX = circleSvgRect.left - parentRect.left;
let leftTopY = circleSvgRect.top - parentRect.top;
leftTopX = leftTopX + 15 - 5;
leftTopY = leftTopY + 15 - 5;
var degree = (20 * Math.PI) / 180;
var xc = 250;
var yc = 250;
leftTopX =
(leftTopX - xc) * Math.cos(degree) -
(leftTopY - yc) * Math.sin(degree) +
xc;
leftTopY =
(leftTopX - xc) * Math.sin(degree) +
(leftTopY - yc) * Math.cos(degree) +
yc;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', leftTopX + 'px');
c.style.setProperty('top', leftTopY + 'px');
elParent.appendChild(c);
});
To see result make click inside red circle. Withour rotation a green circle is placed in the center of red circle. Otherwise has offset.
the maths should be something like this, but the solution needs some additional calculations for the rotation of the red circle itself within the outer rectangle.
Note 1: The margin of the body is removed for simplicity...
Note 2: Scrolls effect the script a lot. Therefore the solution also may not be very useful without taking it into consideration...
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
const degree = getCurrentRotation(document.getElementById('parent'));
const xcenter = parentRect.width / 2 + parentRect.left;
const ycenter = parentRect.height / 2 + parentRect.top;
const dx = (circleSvgRect.left + 10) - xcenter;
const dy = ycenter - (circleSvgRect.top + 10);
console.log(dx + ' - ' + dy + '-' + Math.atan(dy / dx));
const r = Math.sqrt(dx * dx + dy * dy);
const curDegree = Math.atan(dy / dx) + degree;
xnew = xcenter + Math.sign(-dx) * Math.sin(curDegree) * r;
ynew = ycenter - Math.sign(-dx) * Math.cos(curDegree) * r;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', xnew + 'px');
c.style.setProperty('top', ynew + 'px');
elParent.appendChild(c);
});
//https://stackoverflow.com/questions/19574171/how-to-get-css-transform-rotation-value-in-degrees-with-javascript
function getCurrentRotation(el) {
var st = window.getComputedStyle(el, null);
var tm =
st.getPropertyValue('-webkit-transform') ||
st.getPropertyValue('-moz-transform') ||
st.getPropertyValue('-ms-transform') ||
st.getPropertyValue('-o-transform') ||
st.getPropertyValue('transform') ||
'none';
if (tm != 'none') {
var values = tm
.split('(')[1]
.split(')')[0]
.split(',');
return (angle = Math.atan2(values[1], values[0]));
}
return 0;
}
<div id="parent">
<div id="circle" style="left: 100px; top: 100px"></div>
</div>
<style>
body {
margin:0px;
padding:0px;
}
#circle {
width: 30px;
height: 30px;
border-radius: 50%;
background: red;
position: relative;
}
#c {
position: absolute;
width: 10px;
height: 10px;
background: green;
border-radius: 50%;
}
#parent {
width: 500px;
position: relative;
height: 500px;
border: 1px solid #ccc;
transform: rotate(180deg);
}
</style>

Get center coordinates of circle sector

I need to set up <text> element in the center of pie chart segments in an svg <circle>. Right now I use this formula for coordinates:
x(t) = r cos(t) + j
y(t) = r sin(t) + j
where t must be radians. Actually, it works good the first point. But next points are wrong (see code snippet). The question is do I use the wrong formula?
It's my calculations for <text> coordinates
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
//Pie chart plugin
function initPieChart(segmentsData) {
var data = [];
for (var i = 0; i < segmentsData.length; i++) {
var percent = segmentsData[i].getAttribute('data-percent');
var bgcolor = segmentsData[i].getAttribute('data-bg-color');
var textcolor = segmentsData[i].getAttribute('data-text-color');
data.push({"bgcolor": bgcolor, "textcolor": textcolor, "value" : Number(percent)});
}
var angle = -90;
var textAngleOffset = -90;
// Setup global variables
var svg = document.getElementById('pie-chart'),
list = document.getElementById('pie-values'),
totalValue = 0,
radius = 94,
circleLength = Math.PI * (radius * 2), // Circumference = PI * Diameter
spaceLeft = circleLength;
// Get total value of all data.
for (var i = 0; i < data.length; i++) {
totalValue += data[i].value;
}
function degrees_to_radians(degrees){
var pi = Math.PI;
return degrees * (pi/180);
}
function animate(circle, segmentLength, circleLength) {
// circle.setAttribute("stroke-dasharray", spaceLeft + " " + circleLength);
circle.setAttribute("stroke-dasharray", circleLength *segmentLength + " " + circleLength);
}
var segmentOffset = 0;
var animationDelay = 0;
// Loop trough data to create pie
for (var c = 0; c < data.length; c++) {
var segmentLength = data[c].value/100;
var angleOffset = (data[c].value) *360 + angle;
animationDelay = animationDelay + 800;
if(c>0) {
segmentOffset = segmentOffset -data[c-1].value/100*circleLength;
textAngleOffset = (data[c].value/100) *360 + textAngleOffset;
}
// Create circle
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// Create group for each segment
var group = document.createElementNS("http://www.w3.org/2000/svg", "g");
group.classList.add("segment-group");
//Create text
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
text.setAttribute("text-anchor", "middle");
text.setAttribute("fill", data[c].textcolor);
text.innerHTML = data[c].value + '%';
// Set attributes (self explanatory)
circle.setAttribute("class", "pie-chart-value");
circle.setAttribute("cx", 188.5);
circle.setAttribute("cy", 188.5);
circle.setAttribute("r", radius);
circle.setAttribute("transform", "rotate(" + angleOffset + ", 188.5, 188.5)");
// Set dash on circle
circle.setAttribute("stroke-dasharray", "0" + " " + circleLength);
setTimeout(animate, animationDelay, circle, segmentLength, circleLength);
if(c>0) {
circle.setAttribute("stroke-dashoffset", segmentOffset);
}
// Set Stroke color
circle.style.stroke = data[c].bgcolor;
//Append circle and text to group
group.appendChild(circle);
group.appendChild(text);
// Append group to svg.
svg.appendChild(group);
}
}
//Pie chart call
var chartSegments = document.getElementsByClassName('pie-segment');
initPieChart(chartSegments);
/* Pie chart styles */
.pie-chart-value {
fill: none;
stroke-width: 188.5;
transition: stroke-dasharray 800ms linear;
}
/* */
.time-statistics {
padding-top: 30px;
}
.chart-value {
position: relative;
margin-bottom: 5px;
}
.chart-value:before {
display: none;
}
.chart-value .dot {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 10px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.pie-chart-container {
position: relative;
}
.pie-chart-bg {
position: absolute;
top: 0px;
left: 0;
z-index: -1;
}
.pie-chart-content {
position: absolute;
top: 0px;
left: 0px;
}
<div class="pie-chart-container">
<span class="pie-segment" data-percent="20" data-bg-color="#d8d8d8" data-text-color="#123431"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#345a57" data-text-color="white"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#133532" data-text-color="white"></span>
<div class="pie-chart-content">
<svg id="pie-chart" width="377" height="377"></svg>
</div>
</div>
You need to adjust the textoffset for the previous value, not the current one. I.e.:
textAngleOffset = (data[c-1].value/100) *360 + textAngleOffset;
Here is working code:
//Pie chart plugin
function initPieChart(segmentsData) {
var data = [];
for (var i = 0; i < segmentsData.length; i++) {
var percent = segmentsData[i].getAttribute('data-percent');
var bgcolor = segmentsData[i].getAttribute('data-bg-color');
var textcolor = segmentsData[i].getAttribute('data-text-color');
data.push({"bgcolor": bgcolor, "textcolor": textcolor, "value" : Number(percent)});
}
var angle = -90;
var textAngleOffset = -90;
// Setup global variables
var svg = document.getElementById('pie-chart'),
list = document.getElementById('pie-values'),
totalValue = 0,
radius = 94,
circleLength = Math.PI * (radius * 2), // Circumference = PI * Diameter
spaceLeft = circleLength;
// Get total value of all data.
for (var i = 0; i < data.length; i++) {
totalValue += data[i].value;
}
function degrees_to_radians(degrees){
var pi = Math.PI;
return degrees * (pi/180);
}
function animate(circle, segmentLength, circleLength) {
// circle.setAttribute("stroke-dasharray", spaceLeft + " " + circleLength);
circle.setAttribute("stroke-dasharray", circleLength *segmentLength + " " + circleLength);
}
var segmentOffset = 0;
var animationDelay = 0;
// Loop trough data to create pie
for (var c = 0; c < data.length; c++) {
var segmentLength = data[c].value/100;
var angleOffset = (data[c].value) *360 + angle;
animationDelay = animationDelay + 800;
if(c>0) {
segmentOffset = segmentOffset -data[c-1].value/100*circleLength;
textAngleOffset = (data[c-1].value/100) *360 + textAngleOffset;
}
// Create circle
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// Create group for each segment
var group = document.createElementNS("http://www.w3.org/2000/svg", "g");
group.classList.add("segment-group");
//Create text
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
text.setAttribute("text-anchor", "middle");
text.setAttribute("fill", data[c].textcolor);
text.innerHTML = data[c].value + '%';
// Set attributes (self explanatory)
circle.setAttribute("class", "pie-chart-value");
circle.setAttribute("cx", 188.5);
circle.setAttribute("cy", 188.5);
circle.setAttribute("r", radius);
circle.setAttribute("transform", "rotate(" + angleOffset + ", 188.5, 188.5)");
// Set dash on circle
circle.setAttribute("stroke-dasharray", "0" + " " + circleLength);
setTimeout(animate, animationDelay, circle, segmentLength, circleLength);
if(c>0) {
circle.setAttribute("stroke-dashoffset", segmentOffset);
}
// Set Stroke color
circle.style.stroke = data[c].bgcolor;
//Append circle and text to group
group.appendChild(circle);
group.appendChild(text);
// Append group to svg.
svg.appendChild(group);
}
}
//Pie chart call
var chartSegments = document.getElementsByClassName('pie-segment');
initPieChart(chartSegments);
/* Pie chart styles */
.pie-chart-value {
fill: none;
stroke-width: 188.5;
transition: stroke-dasharray 800ms linear;
}
/* */
.time-statistics {
padding-top: 30px;
}
.chart-value {
position: relative;
margin-bottom: 5px;
}
.chart-value:before {
display: none;
}
.chart-value .dot {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 10px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.pie-chart-container {
position: relative;
}
.pie-chart-bg {
position: absolute;
top: 0px;
left: 0;
z-index: -1;
}
.pie-chart-content {
position: absolute;
top: 0px;
left: 0px;
}
<div class="pie-chart-container">
<span class="pie-segment" data-percent="20" data-bg-color="#d8d8d8" data-text-color="#123431"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#345a57" data-text-color="white"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#133532" data-text-color="white"></span>
<div class="pie-chart-content">
<svg id="pie-chart" width="377" height="377"></svg>
</div>
</div>

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

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>

Need help to Modify HTML5 Audio Analyser bar graphic

There is a custom animated HTML audio analyzer graphic that plays an audio track and moves based on the frequencies of that audio.
This is the code from CodePen HERE, I've found out that it only works on HTTPS domain only.
Now the problem is: I don't need to upload an audio track like what the code does, I just need a simple audio track to play automatically and removing that upload button. let's say I have a track1.mp3 in the same directory on the server and want to play it when my HTML page is loaded.
window.onload = function() {
var file = document.getElementById("thefile");
var audio = document.getElementById("audio");
file.onchange = function() {
var files = this.files;
audio.src = URL.createObjectURL(files[0]);
audio.load();
audio.play();
var context = new AudioContext();
var src = context.createMediaElementSource(audio);
var analyser = context.createAnalyser();
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame);
x = 0;
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
var r = barHeight + (25 * (i / bufferLength));
var g = 250 * (i / bufferLength);
var b = 50;
ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
}
audio.play();
renderFrame();
};
};
#thefile {
position: fixed;
top: 10px;
left: 10px;
z-index: 100;
}
#canvas {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
audio {
position: fixed;
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
<div id="content">
<input type="file" id="thefile" accept="audio/*" />
<canvas id="canvas"></canvas>
<audio id="audio" controls></audio>
</div>
Google Forces Yet Another Policy
Nothing is sacred to these guys -- as of Dec 2018 New autoplay policies have been enacted upon Chrome users developing Web Audio API. If the AudioContext(); is created before the user interacts with a gesture (click, tap, burp, snore, etc), the AudioContext(); will be suspended until the user does so.
So to adjust for this engineering marvel I added a play button and wrapped everything in an eventListener.
Changing src
"Now the problem is: I don't need to upload an audio track like what the code does, I just need a simple audio track to play automatically and removing that upload button. let's say I have a track1.mp3 in the same directory and want to play it when my page is loaded."
OK, the demo has been adapted to load a normal url, you'll need to change this line so that it points to the location of the file on your server:
audio.src = "https://host.top/path/to/file.mp3";
The new line that's above the previously mentioned line is added for certain conflicts with CORS:
audio.crossOrigin = "anonymous";
Plunker
Demo
Note: If this Stack Snippet has no sound, then go to this Plunker
document.getElementById('load').addEventListener('click', audioViz);
function audioViz(e) {
var player = document.getElementById("player");
player.crossOrigin = "anonymous";
player.src = "https://glsbx.s3-us-west-1.amazonaws.com/-/dd.mp3";
player.load();
player.play();
var context = new AudioContext();
var src = context.createMediaElementSource(player);
var analyser = context.createAnalyser();
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var barWidth = (WIDTH / bufferLength) * 2.5;
var barHeight;
var x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame);
x = 0;
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
var r = barHeight + (25 * (i / bufferLength));
var g = 250 * (i / bufferLength);
var b = 50;
ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
x += barWidth + 1;
}
}
player.play();
renderFrame();
}
button {
position: fixed;
top: 46px;
left: 46px;
z-index: 100;
display: inline-block;
font-size: 48px;
border: none;
background: none;
color: rgba(223, 6, 39, 0.8);
cursor: pointer;
}
button:hover {
color: rgba(255, 0, 128, 0.8);
}
button:focus {
outline: 0
}
#canvas {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
#player {
position: fixed;
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
<button id='load' class='load' type='button'>▶</button>
<canvas id="canvas"></canvas>
<audio id="player" controls>
<source src='about:blank'>
</audio>

Categories

Resources