How to draw lines dynamically on SVG Picture? - javascript

I'm trying to develop an Attack Map when basically like all maps it will show the "Attacks" that are happening over the world but basically it will be randomly as I don't have access to any AV's APIs to get correct data. As of now I only have this SVG map shown on my HTML page:
And I'd want to draw some lines from one country to another to simulate the attacks. I have been searching about this and I have seen two "solutions". One is a JS code that draws a line in HTML:
if (stroke){
ctx.strokeStyle = stroke;
}
if (width){
ctx.lineWidth = width;
}
ctx.beginPath();
ctx.moveTo(...begin);
ctx.lineTo(...end);
ctx.stroke();
}
const canvas = document.querySelector("#line");
if(canvas.getContext){
const ctx = canvas.getContext('2d');
drawLine(ctx, [100, 100], [300, 100], 'green', 5)
}
but as I said this draws a line outside of the SVG map and inside of HTML. I also saw a line tag which can be placed inside of SVG tags but it is static. I want to be dynamic and simulate the attacks. Is there any way I can do this? Thank you for your time!

Even if the SVG element is static, you can add <line /> elements dynamically when the DOM has loaded:
const lines = [
{
from: { x: 0, y: 20 },
to: { x: 30, y: 60 }
},
{
from: { x: 0, y: 20 },
to: { x: 30, y: 60 }
}
];
function addLine (x1, y1, x2, y2) {
const line = document.createElementNS('http://www.w3.org/2000/svg','line');
line.setAttribute("x1", x1);
line.setAttribute("y1", y1);
line.setAttribute("x2", x2);
line.setAttribute("y2", y2);
line.setAttribute("stroke", "white");
document.getElementById("mySvg").appendChild(line);
}
addEventListener("DOMContentLoaded", function () {
for (const line of lines) {
addLine(line.from.x, line.from.y, line.to.x, line.to.y);
}
});

Related

how do i place a circle on specific places in grid (canvas)

so I am trying to make thisgame called GO and I need to place circles in the edges like this. I've made the grid and now need to place the circles in there. I 'v tried different things like using the arc in canvas with mouse position and placing it but it isn't working something else I tried is to make an array that checks where the lines cross but it still didn't do anything. but i may have done it wrong. I'm not sure what's wrong so hope you guys could help me find a way to place the circles on the board every time I click the mouse. I've deleted the things that didn't work and this is my code now:
const canvas = document.getElementById("myCanvas")
const ctx = canvas.getContext("2d")
//canvas.style.border = "1px solid black"
let w = ctx.canvas.width
let h = ctx.canvas.height
goBoard = []
goCheckBoard = []
function drawGrid(w, h) {
for (x = 0; x <= w; x += 40) {
for (y = 0; y <= h; y += 40) {
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
ctx.stroke();
ctx.moveTo(0, y);
ctx.lineTo(w, y);
ctx.stroke();
}
}
}
drawGrid(400, 400)
this just makes the grid
one example i've tried is this:
mouseClicked = function () {
ctx.beginPath()
ctx.strokeStyle = "black"
ctx.ellipse(mouseX, mouseY, 20, 20);
ctx.stroke()
};
another:
function rtn(n, r){
return Math.round(n/r)*r;
}
canvas.onclick = function(event){
ellipse(rtn(event.clientX, 40), rtn(event.clientY, 40), 180, 180);
};
im not sure if that is the correct way to do it
maybe make an array of all the possible places to place the circle but im not sure how
here is a fiddle if you want to test it out https://jsfiddle.net/pwe0vx7o/
you first need to change the ellipse(...) to ctx.ellipse(...), because ellipse isn't a global function, but a metod of the CanvasRenderingContext2D.
Through the docs I also found that this function takes 7 arguments so added ones for radiusX, radiusY, rotation, startAngle, endAngle.
Here is also a fiddle for the finished result: https://jsfiddle.net/c6udn9gf/8/
This will get you close, but you need to figure out something with your rounding function.
canvas.onclick = function (event) {
ctx.beginPath();
const x = rtn(event.clientX, 40);
const y = rtn(event.clientY, 40);
ctx.ellipse(x - 20, y - 20, 10, 10, 0, 0, 360);
ctx.fill();
};

p5.js How would I prevent a small circle from crossing a diameter of a bigger circle

Im working of a program that has a circle moving around inside another bigger circle.
var offX;
function setup() {
createCanvas(400, 400);
offX = 0.00;
}
function draw() {
background(220);
var bigBoy = {
x: 200,
y: 200,
r: 150,
};
var smallBoy = {
x: noise(offX) * 400,
y: map(sin(offX),-1,1,10,380),
r: 10,
};
offX += 0.005;
ellipse(bigBoy.x,bigBoy.y,bigBoy.r * 2);
ellipse(smallBoy.x,smallBoy.y,smallBoy.r * 2);
var d = dist(bigBoy.x,bigBoy.y,smallBoy.x,smallBoy.y);
text(round(d,0),30,20);
//-------------------------------//
if(d > bigBoy.r - smallBoy.r){
//move away from / dont cross over bigBoy's diameter//
} else{
//crack on mate//
}
}
could anyone advise me how I would keep the smaller circle within the bigger circles diameter. I would need it to look natural, like the small circle has a force preventing it from leaving the bigger one?
Thanks in advance!
P

How to implement rotation of multiple images around an off-centre point in p5.js

I'm making a tower defense game using JavaScript and p5.js library. I have 2 images a base and a gun. The gun is drawn on top of the base to make it appear as a single unit. I need my gun to point towards the enemy(which follows a path). I need help to make the gun rotate on a point(not centre), keeping in mind that there can be several of these towers. I have tried translating(to change centre) and rotating but this doesn't work for many objects and obviously can't keep track of many objects.
I haven't seen any other question regarding this matter either, is there a better solution/alternative to what I'm trying to accomplish?
Required Code
Some Important Variables
var isFireTowerPressed = false; // checks if tower is placed
var FireTowerPos = []; // location of every tower => [] - 2d array
Preloaded Stuff
function preload() {
backgroundImg = loadImage("http://127.0.0.1:8080/img/extra/map1.png");
[...]
firetowerbaseImg = loadImage("http://127.0.0.1:8080/img/towers/firetowerbase.png");
firetowerturretImg = loadImage("http://127.0.0.1:8080/img/towers/firetowergun.png");
}
Draw Every Frame
function draw()
{
background(60, 238, 161);
[...]
if (isFireTowerPressed == true) //checks if I have pressed the button to place the tower
{
image(firetowerbaseImg, mouseX - 28, mouseY - 28);
// show range circle
noFill();
stroke(0,0,0);
strokeWeight(1);
circle(mouseX, mouseY, 300);
}
for (var i = 0; i < FireTowerPos.length; i++)
{
image(firetowerbaseImg, FireTowerPos[i][0], FireTowerPos[i][1]);
image(firetowerturretImg, FireTowerPos[i][0], FireTowerPos[i][1]-20);
}
}
Mouse Click Event
function mouseClicked()
{
if (isFireTowerPressed==true && mouseX+28 <= 750) // place-able area
{
FireTowerPos.push([mouseX-28, mouseY-28]);
isFireTowerPressed = false;
}
}
The picture shows the 2 pictures I'm using(base & gun). I need to be able to rotate the gun towards the enemy
Any help is appreciated, thank you
Translating and rotating works for several objects if you also use the push() and pop() methods, from the p5 library, which allow you to store the current settings.
To rotate towards a given point the function atan2(y2 - y1, x2 - x1) is the commonly used method.
To illustrate, I wrote this quick snippet in which the guns will rotate towards the mouse only if the mouse is within range of the gun.
let gunSprite
function preload(){
gunSprite = loadImage("https://i.imgur.com/ayvg9J2.jpg", ()=>{
gunSprite.resize(20, 40)
})
}
let guns = [
{ x: 160, y: 80, angle: 0, range: 100 },
{ x: 300, y: 200, angle: 0, range: 150 },
{ x: 100, y: 240, angle: 0, range: 120 }
]
function setup(){
createCanvas(600, 400)
noFill()
}
function draw(){
background(200)
for(let gun of guns)
drawGun(gun)
}
function drawGun(gun){
const isWithinRange = dist(mouseX, mouseY, gun.x, gun.y) < gun.range
if(isWithinRange)
gun.angle = atan2(mouseY - gun.y, mouseX - gun.x) + radians(90)
push()
translate(gun.x, gun.y)
rect(-25, -20, 50, 40) // Draw the gun base
ellipse(0, 0, gun.range*2) // display the gun range
rotate(gun.angle)
image(gunSprite, -10, -40) // Set the offset of the gun sprite and draw the gun
pop()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>

shape intersection with KineticJS

I want to show only intersection of two shape by using KineticJS.
How can I do this?
I tried to do it like following link.
HTML5 Canvas Clipping Region. Is have any other way?
You can use the globalCompositeOperation to do this: http://jsfiddle.net/wbzwX/
ctx.fillStyle="#000";
ctx.fillRect(50,50,100,100);
ctx.globalCompositeOperation = "source-in";
// this will use the fillstyle of the next drawn object.
// "destination-in" will use the previous fillstyle.
ctx.beginPath();
ctx.arc(100,50,30,0,Math.PI*2,false);
ctx.closePath();
ctx.fillStyle="#f00";
ctx.fill();​
I have created the solution based on Shmi.
function makeShapeComposite(shape, operation) {
shape.attrs._drawFunc = shape.attrs.drawFunc;
shape.attrs.drawFunc = function (context) {
context.save();
context.globalCompositeOperation = operation;
this.attrs._drawFunc.call(this, context);
context.restore();
};
return shape;
};
var pol= makeShapeComposite(new Kinetic.RegularPolygon({
x: 250,
y: 100,
sides: 4,
radius: 70,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 2
}), "destination-in");
Fiddle:http://jsfiddle.net/sara9/2v7W2/5/
Refer this tutorial.

Drawing shapes and lines with HTML5 Canvas and jQuery

I have an upcoming project that I would like to use the HTML5 canvas element to accomplish what would have had to be done in the past with either images and absolutely paced div's or Flash. Here is a basic example of the concept
Here are my concerns:
I am ok with using div's with corner radius to create the circles as they will be styled, and I'm not sure if I can do that with a mix of svg and the canvas element.
My main concern is the stroke that joins the outer circles to the inner, I would like to do this with canvas but am not sure A) How to get multiple canvas elements on one page in one containing element (a wrapper div) and B) how to figure out the starting points, I would assume the ending point would just be the center of the wrapper div (IE if its 600x600 = x=300, y=300)
Can anyone shed some light on this and offer any suggestions? Is there an advantage to using any of the jQuery canvas plugiins over vanilla JS?
thank you!
The canvas API consists of some functions which seem to do the job just fine:
.moveTo/.lineTo for a line path
.arc for a circle path
.stroke to stroke a path (line)
.fill to fill a path (circle)
Here's a very trivial proof of concept: http://jsfiddle.net/eGjak/275/.
I've used (x, y) for both the lines and the circles, which means the lines go from and to the midpoint of two circles. r is the radius of a circle.
var ctx = $('#cv').get(0).getContext('2d');
var circles = [ // smaller circles
{ x: 50, y: 50, r: 25 },
{ x: 250, y: 50, r: 25 },
{ x: 250, y: 250, r: 25 },
{ x: 50, y: 250, r: 25 },
];
var mainCircle = { x: 150, y: 150, r: 50 }; // big circle
function drawCircle(data) {
ctx.beginPath();
ctx.arc(data.x, data.y, data.r, 0, Math.PI * 2); // 0 - 2pi is a full circle
ctx.fill();
}
function drawLine(from, to) {
ctx.beginPath();
ctx.moveTo(from.x, from.y);
ctx.lineTo(to.x, to.y);
ctx.stroke();
}
drawCircle(mainCircle); // draw big circle
$.each(circles, function() { // draw small circles and lines to them
drawCircle(this);
drawLine(mainCircle, this);
});​
You could just do all of these circles in CSS. Get some divs, style them as you like in CSS, and then apply border-radius: 100; to the object, and done. I hope this helped.

Categories

Resources