When I click on button each time it gives a different shape.All the shapes are dynamic. It can be polygon or circle (hundreds of shapes).
The shape is formed by group of lines.
The issue here is each shape gets positioned at different place and get scaled smaller then the other.I want them to be normalized. All the shapes should have proper scaling effect and positioned at same x position. Some of the shapes come in center , some go a bit towards top left.
Code with same transform matrix and scale is shown below.Shapes get positioned differently.May be the problem is coordinates of line.In the first code snippet it starts at (0,0) and last shapes line start at (15,5)
Can I give the group g positioned at same position for all shapes.Should I place relative to something?
var draw = SVG('drawing').viewbox(0, 0, 400, 400).attr("preserveAspectRatio", "xMidYMid meet");
var group = draw.group().translate(90, 90).scale(3)
var obj = {
"type": "Polygon",
"coords": [
[
[0, 0],
[30, 0],
[30, 20],
[60, 20],
[60, 40],
[0, 40],
[0, 0]
],
[
[0, 0],
[10, 50],
[50, 10],
[0, 0]
],
[
[0, 0],
[60, 0],
[80, 40],
[0, 40],
[0, 0]
],
[
[0, 0],
[50, 0],
[50, 20],
[0, 20],
[0, 0]
],
[
[50, 10],
[40, 40],
[20, 40],
[10, 20],
[50, 10]
],
[
[15, 5],
[40, 10],
[10, 20],
[5, 10],
[15, 5]
],
[
[20, 35],
[10, 30],
[10, 10],
[30, 5],
[45, 20],
[20, 35]
]
]
};
shapehandler()
function shapehandler() {
if (obj.coords.length) {
group.clear();
drawShape(obj.coords[0]);
obj.coords.shift();
}
}
function drawShape(coords) {
var lineCoords = [];
var pointListString = coords.toString();
var pointListArray = JSON.parse("[" + pointListString + "]");
for (let i = 0; i < pointListArray.length - 2; i += 2) {
let [x1, y1, x2, y2] = pointListArray.slice(i, i + 4)
lineCoords.push({
x1,
y1,
x2,
y2
});
}
lineCoords.forEach(function (lin, i) {
let colorShade = [
'#FFDC0B',
'#002438',
'#9B56BB',
'#c6c7e2',
'#318700',
'#fe854f',
'#FF8400',
'#31d0c6',
'#7c68fc',
'#61549C',
'#6a6c8a',
'#4b4a67',
'#3c4260',
'#33334e',
'#222138'
];
group.line(lin.x1, lin.y1, lin.x2, lin.y2).stroke({ color: colorShade[i], width: 4, linecap: 'square' });
});
}
html, body {
margin: 0;
padding: 0;
font-family: Arial;
}
svg {
width: 100%;
height: 100%;
}
#drawing{
margin: 20px;
display: inline-block;
position: relative;
border: 1px solid darkgrey;
overflow:hidden;
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.6/svg.js"></script>
<div id="toolbar">
<button type="button" id="btn-show-shape" onclick="shapehandler()">Show Polygon Shapes</button>
</div>
<div id="drawing">
</div>
I'm keeping your HTML.
The CSS is yours but I've added a rule for lines. It sets the stroke-width. For a nicer effect the stroke-linecap is round.
The most important: I'm using vector-effect:non-scaling-stroke. Since I don't know how much I will scale the group, I need vector-effect:non-scaling-stroke that causes an object's stroke-width to be unaffected by transformations and zooming.
In the javaScript I'm keeping all your data (points and colors), but I've rewrite the rest.
The most important thing; I'm calculating the scale which depends on the group's bounding box width. I'm translating the group in the center of the SVG canvas and scaling it.
I hope this is what you need.
const SVG_NS = 'http://www.w3.org/2000/svg';
const W = 400,cx = W/2;
const H = 400,cy = H/2;
let obj = {
type: "polygon",
coords: [
[
[0, 0],
[30, 0],
[30, 20],
[60, 20],
[60, 40],
[0, 40],
[0, 0]
],
[
[0, 0],
[10, 50],
[50, 10],
[0, 0]
],
[
[0, 0],
[60, 0],
[80, 40],
[0, 40],
[0, 0]
],
[
[0, 0],
[50, 0],
[50, 20],
[0, 20],
[0, 0]
],
[
[50, 10],
[40, 40],
[20, 40],
[10, 20],
[50, 10]
],
[
[15, 5],
[40, 10],
[10, 20],
[5, 10],
[15, 5]
],
[
[20, 35],
[10, 30],
[10, 10],
[30, 5],
[45, 20],
[20, 35]
]
]
};
let colorShade = [
'#FFDC0B',
'#002438',
'#9B56BB',
'#c6c7e2',
'#318700',
'#fe854f',
'#FF8400',
'#31d0c6',
'#7c68fc',
'#61549C',
'#6a6c8a',
'#4b4a67',
'#3c4260',
'#33334e',
'#222138'
];
// create a new SVG element
let svg = drawSVGElmt(
"svg",
{
viewbox:`0 0 ${W} ${H}`,
preserveAspectRatio:"xMidYMid meet",
},
drawing);
// create a group element
let group = drawSVGElmt(
"g",
{/*transform:"translate(90,90) scale(3)"*/},
svg
)
// draw a red dot in the middle of the canvas
drawSVGElmt("circle",{cx:cx,cy:cy,r:5,fill:"red"},svg)
let n = 0;
function drawAndScale(n){
//first remove all the lines from the group
while (group.firstChild) {
group.removeChild(group.firstChild);
}
// for all the points in obj.coords[n] draw a line
for(let i = 0, l = obj.coords[n].length -1; i < l; i++){
let p0 = obj.coords[n][i];
let p1 = obj.coords[n][i + 1];
let x1 = p0[0],y1 = p0[1];
let x2 = p1[0],y2 = p1[1];
let stroke = colorShade[i];
drawSVGElmt("line", {x1:x1,y1:y1,x2:x2,y2:y2,stroke:stroke}, group)
}
//get the size of the bounding box of the group
let BB = group.getBBox();
// set the scate using the width of the bounding box
let scale = (W * .75) / BB.width;
// scale & translate the group in the crnter of the SVG element
group.setAttributeNS(null,"transform",
`translate(${ scale * (-BB.x -BB.width/2)}, ${ scale * (-BB.y -BB.height/2)})
scale(${scale})
translate(${cx/scale}, ${cy/scale})`);
}
drawAndScale(n);
function shapehandler(){
if(n < obj.coords.length - 2){ n++; }else{n = 0};
drawAndScale(n);
}
// a function to draw an SVG element
function drawSVGElmt(type, o, _parent) {
let elmt = document.createElementNS(SVG_NS, type);
for (var name in o) {
if (o.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, o[name]);
}
}
_parent.appendChild(elmt);
return elmt;
}
html, body {
margin: 0;
padding: 0;
font-family: Arial;
}
svg {
width: 100%;
height: 100%;
}
#drawing{
margin: 20px;
display: inline-block;
position: relative;
border: 1px solid;
overflow:hidden;
box-sizing: border-box;
width:400px;
height:400px;
}
line{
stroke-width:50px;
stroke-linecap: round;
/* vector-effect:non-scaling-stroke causes an object's stroke-width to be unaffected by transformations and zooming */
vector-effect:non-scaling-stroke;}
<div id="toolbar">
<button type="button" id="btn_show_shape" onclick="shapehandler()">Show Polygon Shapes</button>
</div>
<div id="drawing">
</div>
I want a function that works like this:
playSound(345, 1000)
Which would play a tone of 345 hz for 1000 milliseconds. What is the simplest way to achieve this in JavaScript? I don't mind if it uses a sample (maybe of a sin wave, or piano), or uses the computer's hardware to generate the sound.
As already pointed out in the comments, the way to do it is through the OscillatorNode.
// create web audio api context
var audioCtx = new(window.AudioContext || window.webkitAudioContext)();
function playNote(frequency, duration) {
// create Oscillator node
var oscillator = audioCtx.createOscillator();
oscillator.type = 'square';
oscillator.frequency.value = frequency; // value in hertz
oscillator.connect(audioCtx.destination);
oscillator.start();
setTimeout(
function() {
oscillator.stop();
playMelody();
}, duration);
}
function playMelody() {
if (notes.length > 0) {
note = notes.pop();
playNote(note[0], 1000 * 256 / (note[1] * tempo));
}
}
notes = [
[659, 4],
[659, 4],
[659, 4],
[523, 8],
[0, 16],
[783, 16],
[659, 4],
[523, 8],
[0, 16],
[783, 16],
[659, 4],
[0, 4],
[987, 4],
[987, 4],
[987, 4],
[1046, 8],
[0, 16],
[783, 16],
[622, 4],
[523, 8],
[0, 16],
[783, 16],
[659, 4]
];
notes.reverse();
tempo = 100;
playMelody();
There is a library called simpleTones.js that greatly simplifies the Web Audio API to do exactly what you are attempting.
Once the library is included in your project, playing a timed frequency is as easy as calling
playTone(345, sine, 1)
345 being the frequency in Hz, sine being the wave pattern(there are other wave pattern options as well) and "1" being one second, or 1000 milliseconds.
You can download the library and read the documentation here: https://github.com/escottalexander/simpleTones.js
Best of luck on your project.
I've non-map images like floor images.
By using Leaflet image-Overlay I load these images, And with the help of Leaflet-heat plugin I generate heat-map layer on that image.
But heat-map positions and coordinates of image are mismatched.
please help me to solve this problem.
My Output image:My Output
Black dots in yellow box of the image are the points where i have to generate the heat-map.
I mentioned the coordinates of these points below.
var imgDimensions={width:1713, height:1625};
var map = L.map('map',{
maxZoom: 0,
minZoom: 0,
crs:L.CRS.Simple
}).setView([imgDimensions.height/2, imgDimensions.width/2],0);
var imageUrl = "D:/Jithu/LeafLet/images/Floor1.png";
var imageBounds = [
[imgDimensions.width , 0],
[0, imgDimensions.height]
];
L.imageOverlay(imageUrl, imageBounds).addTo(map);
addressPoints = addressPoints.map(function (p) {
var contPoint = map.layerPointToContainerPoint(L.point(p[0],p[1]));
var latlong = map.layerPointToLatLng(layerPoint);
return [latlong.lat,latlong.lng,p[2]];
});
var heat = L.heatLayer(addressPoints, {
minOpacity:0.0,
max:1.0,
radius: 10,
gradient:{
0.4: 'blue',
0.65: 'lime',
1: 'red'
}
}).addTo(map);
// addressPoints.js
//[X-cord, Y-cord, Intensity]
var addressPoints = [
[637, 383, 1],
[724, 397, 0.5],
[682, 444, 0.5],
[714, 515, 1],
[589, 500, 1]
];
<div id="map" style="width: 1713px;height: 1625px"></div>
I am using the jquery flot to show charts with tooltip. I am using ticks to get custom xaxis data. SO
var data = [ [0, 3], [4, 8], [8, 5], [9, 13] ];
var ticksData = [ [0, "A"], [4, "B"], [8, "C"], [9, "D"] ];
......
xaxis: {
ticks: ticksData,
tickLength: 0
},
But when I want to show the tooltip, I got the none ticks data.
$("#placeholder").bind("plothover", function(event, pos, item) {
var x = item.datapoint[0], y = item.datapoint[1];
//x and y are 4,8 instead of B,8
Complete sample http://jsfiddle.net/z0u6rqhe/
Is there any way to get to fix tool tip to show ticks data, or I should loop through ticksData and re find the value
please check this link, i hope this will helpful for you.
jsfiddle.net/z0u6rqhe/5/
code:
var x = item.series.xaxis.ticks[item.dataIndex];