I have a WEBGL canvas in which I am loading a 3d model. I also have a text in variable font which I create with createP. The problem is that I need the text to be between the background and the 3d model. But I can only have the text in front of the canvas (on top of 3d model). Is there any way I can achieve this?
Ps. Creating the text with text() does not allow me to have variable weight value.
let kalameh;
var cnv;
let img;
function preload(){
img = loadImage('assets/lines.png');
kalameh = loadModel('kalameh.obj');
}
function setup() {
cnv = createCanvas(700, 700, WEBGL);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
wordA = createP('my text');
}
function draw() {
background(220, 220, 220);
wordA.style('font-size', '110px');
wordA.style('font-weight', '200');
wordA.style('font-stretch', '200%');
wordA.style('align', 'center');
wordA.position(40,25);
image(img, -1*windowWidth/2, -1*windowHeight/2, windowWidth, windowHeight);
translate (0,0,100);
pointLight(255,255,255, -350,0,400);
pointLight(255,255,255, 350,0,400);
ambientMaterial(255);
noStroke();
scale (0.25);
model(kalameh);
}
You could create two sketches (and thus two canvases) and assign z-index properties of -1 and 1 to make them foreground and background sketches, respectively. You can then sandwich the paragraph element that you created between the two canvases by giving it a z-index of 0. You can then make the foreground sketch transparent by calling clear() at the beginning of the draw loop.
In the code snippet below, the 3D object is in front of the text paragraph, whereas the white square of the "background" is behind the text.
let testP;
new p5(function(p){
p.setup = function() {
const foregroundCanvas = p.createCanvas(400, 400, p.WEBGL);
foregroundCanvas.id("foregroundSketch");
foregroundCanvas.position(0, 0);
p.normalMaterial();
testP = p.createP("In front of background / behind object ")
testP.position(95, 115);
testP.id("sandwichedParagraph")
p.angleMode(p.RADIANS)
}
p.draw = function() {
p.clear();
//drag to move the world.
// p.orbitControl();
p.push();
let rotateAngle = p.sin(p.frameCount/50);
p.rotateX(rotateAngle/2);
p.rotateY(-rotateAngle);
p.rotateZ(rotateAngle);
p.box(200, 100, 40);
p.pop();
}
}, "foregroundSketch");
new p5(function(p){
p.setup = function() {
const backgroundCanvas = p.createCanvas(400, 400);
// backgroundCanvas.parent("wrapper")
backgroundCanvas.position(0, 0);
backgroundCanvas.id("backgroundSketch")
p.noStroke();
}
p.draw = function() {
p.background(200);
let shiftAmount = p.map(p.sin(p.frameCount/60), -1, 1, 80, 310);
p.rect(shiftAmount, 120, 40, 40);
}
}, "backgroundSketch");
html, body {
margin: 0;
padding: 0;
}
/* The sketch with the white square has z-index of -1 (background!) */
#backgroundSketch {
z-index: -1;
position: absolute;
}
/* The <p> has z-index of 0 (sandwiched between both sketches)*/
#sandwichedParagraph {
z-index: 0;
position: absolute;
}
/* The sketch with the object has z-index of 1 (foreground!)*/
#foregroundSketch {
z-index: 1;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
Related
This question already has an answer here:
Is the canvas empty?
(1 answer)
Closed 1 year ago.
I have a web page with two canvas elements stacked on top of each other. This is the basis for some functionality that lets me "erase" the top canvas to reveal an image loaded into the bottom canvas. The functionality works well.
What I'm trying to do now is trigger an event once the top canvas has been completely "erased" i.e. all of the pixels for the top context are transparent. I've found ways on SO to check a particular pixel's alpha value via getImageData but I'm trying to figure out a way to determine when the very last pixel's alpha value = 0.
I've included my code as well as an unfinished attempt to do this with a for and if loop (but this seems to not be the best approach). Another issue I've discovered is that when I use getImageData a thin grey border appears around two edges of my canvas.
Thanks for any help in advance!
window.onload = function() {
//Move speaker image across page
var speaker = document.getElementById('speaker');
speaker.onload = MoveElement(speaker, "right", 1000);
//Create canvases & contexts
var canvas = document.getElementById('canvas');
var ctxB = canvas.getContext('2d');
var canvas2 = document.getElementById('canvas2');
var ctxT = canvas2.getContext('2d');
//Get waterfall image object
var waterfall = document.getElementById('waterfall');
//Set canvas w&h properties
canvas.width = canvas2.width = .3*waterfall.width;
canvas.height = canvas2.height = .3*waterfall.height;
//Populate Bottom canvas with waterfall image
ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);
//Populate Top canvas with white rectangle
ctxT.fillStyle = "white";
ctxT.fillRect(0, 0, canvas2.width, canvas2.height);
//Make Top canvas "erasable"
canvas2.addEventListener('mousemove', event => {
var x = event.offsetX;
var y = event.offsetY;
const eraseSize = 125;
ctxT.clearRect(x-eraseSize/2, y-eraseSize/2, eraseSize, eraseSize);
})
//Attempt to trigger an event when all pixels of top canvas have alpha = 0
var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
console.log(imageDataTop);
for (var i = 0; i < imageDataTop; i++) {
if (imageDataTop.data[i] = 0) {
//
}
}
}
function PlayAudio() {
document.getElementById('boyfriend').play();
}
//Move an element in a given direction a certain distance
function MoveElement(element, direction, totalDistance) {
//Determine horizontal or vertical direction
var LeftOrTop = (direction=="left" || direction=="right") ? "left" : "top";
//Set default frame distance
var frameDistance = 150;
//Adjust for backwards direction
if (direction=="left" || direction=="up") {
totalDistance *= -1;
frameDistance = -1;
}
//Get style data object for element
var elementStyle = window.getComputedStyle(element);
//Get Left or Top position of element
var positionValue = elementStyle.getPropertyValue(LeftOrTop).replace("px", "");
//Apply direction and distance change to element
var destination = (Number(positionValue) + totalDistance) + "px";
function MoveFrame() {
//If element reaches its destination...
if (elementStyle.getPropertyValue(LeftOrTop) == destination) {
//...stop the interval motion
clearInterval(movingFrames);
}
//Otherwise, continue the interval movement
else {
elementStyle = window.getComputedStyle(element);
positionValue = elementStyle.getPropertyValue(LeftOrTop).replace("px", "");
element.style[LeftOrTop] = (Number(positionValue) + frameDistance) + "px";
}
}
//Define time interval for movement
var movingFrames = setInterval(MoveFrame, 500);
}
#stack {
position: relative;
}
#stack canvas {
position: absolute;
display: block;
left: 50%;
transform: translateX(-50%);
margin-top: 150px;
}
#speaker {
position: absolute;
top: 20px;
animation-duration: 800ms;
animation-name: fadein;
animation-iteration-count: 10;
}
#keyframes fadein {
from {
opacity: 0.25;
}
50% {
opacity: 1;
}
to {
opacity: 0.25;
}
}
<!DOCTYPE html>
{% load static %}
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="{% static 'entrance/entrance.css' %}">
<script src="{% static 'entrance/entrance.js' %}"></script>
</head>
<body>
<p hidden>
<img src="{% static 'entrance/Waterfall.jpg' %}" alt="issue here" id="waterfall" />
</p>
<img src="{% static 'entrance/sound-icon.svg' %}" id="speaker" />
<p id="test"></p>
<audio id="boyfriend" source src="{% static 'entrance/02 30 Minute Boyfriend.mp3' %}" type="audio/mp3"></audio>
<div id="stack" onmouseenter="PlayAudio()">
<canvas id="canvas"></canvas>
<canvas id="canvas2"></canvas>
</div>
</body>
</html>
The dataimage that you get will be an array which has 4 bytes per point on the canvas the first 3 bytes of which are the RGB colors and the 4th one is the alpha.
If the color is transparent this 4th one will be 0. You will need to go through each time some erasing is done looking at every 4th byte in the array. If you come across one that isn't zero you will know that the erasing isn't complete.
This is quite a useful reference: https://www.w3schools.com/tags/canvas_getimagedata.asp
Context
I have a canvas in which I draw an image. I would want to animate it: the image should be zoomed-in (rescaled) in all directions (vertical and horizontal expansions, towards the top, right, bottom, and left sides, all together and at the same time).
Expected results
At each iteration, the image goes x pixels towards the top and the bottom, the left, and the right sides of the canvas: it's a zoom. The pixels of the image that go beyond the canvas become not visible.
Actual results
At each iteration, the image goes x pixels towards the bottom and right sides of the canvas: it's a zoom. The pixels of the image that go beyond the canvas become not visible.
The problem
The image goes x pixels towards the bottom and right sides of the canvas instead of going x pixels towards the top and the bottom, the left, and the right sides of the canvas.
The question
How to make the image go x pixels towards the top and the bottom, the left, and the right sides of the canvas?
Minimal and Testable Example
How to test my example?
Download an image file titled "my_img.jpg", store it in a directory titled "my_dir". You can change the names; think to change them in the below source code too (line to be changed: var images = [ ....).
In this same directory, store my code in a file titled "index.HTML"
Open your browser to read "index.HTML"
Click on the "Start" button, the animation will begin and you will see my problem.
Sources
Comments
Note the use of ctx.drawImage(tmp_canvas, -(tmp_canvas.width - canvas.width)/2, -(tmp_canvas.height - canvas.height)/2);, which is censed to draw the zoomed image (from a new canvas named "tmp_canvas"), in the real canvas (whose context is ctx). I divide by 2 the difference between the zoomed image minus the real canvas, which normally corresponds to the fact to draw the zoomed image expanded towards left AND right. The same techniqye is used for top and bottom sides.
Clues
console.log(-(tmp_canvas.width - canvas.width)/2); shows 0, it should not. tmp_canvas.width should be the zoomed image's width. canvas.width should be the canvas' width.
index.HTML
<html>
<head>
<title>Creating Final Video</title>
</head>
<body>
<button id="start">Start</button>
<canvas id="canvas" width="3200" height="1608"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var images = ["my_dir/my_img.jpg"];
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
function showSomeMedia() {
setImageListener();
setImageSrc();
}
function setImageSrc() {
img.src = images[0];
img.crossOrigin = "anonymous";
}
function imgOnLoad() {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.restore();
var tmp_canvas = canvas.cloneNode();
var tmp_ctx = tmp_canvas.getContext("2d");
function zoomInCanvas() {
tmp_ctx.scale(1.001, 1.001);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(
tmp_canvas,
-(tmp_canvas.width - canvas.width) / 2,
-(tmp_canvas.height - canvas.height) / 2
);
}
var i = 0;
const interval = setInterval(function() {
if (i == 100) {
clearInterval(interval);
}
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.drawImage(canvas, 0, 0);
requestAnimationFrame(zoomInCanvas);
i++;
}, 1000);
}
function setImageListener() {
img.onload = function() {
imgOnLoad();
};
}
$("#start").click(function() {
showSomeMedia();
});
</script>
</body>
</html>
I don't know about how to solve some of the other problems with your code, however I can help with being able to rescale images in all directions.
$(document).ready(function(){
$('#resizable').resizable({
handles: 'n, e, s, w, ne, se, sw, nw'
});
});
#resizable {
width: 50%;
border: 1px solid black;
}
#resizable img {
width: 100%;
}
.ui-resizable-handle {
background: red;
border: 1px solid red;
width: 9px;
height: 9px;
z-index: 2;
}
.ui-resizable-se {
right: -5px;
bottom: -5px;
}
#resizable {
width: 150px;
height: 150px;
padding: 0.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<img id="resizable" src="https://www.w3schools.com/w3css/img_lights.jpg">
Some of this code is from a question that I recently asked, and got an answer for.
In fact, the translate call doesn't change the tmp_canvas's image's dimensions. So I have to compute these new width and height and store them in parralel. The following code works perfectly:
<html>
<head>
<title>Creating Final Video</title>
</head>
<body>
<button id="start">Start</button>
<canvas id="canvas" width=3200 height=1608></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var images = [
'my_dir/my_img.jpg'
];
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
function showSomeMedia() {
setImageListener();
setImageSrc();
}
function setImageSrc() {
img.src = images[0];
img.crossOrigin = "anonymous";
}
function imgOnLoad() {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.restore();
var tmp_canvas = canvas.cloneNode();
var tmp_ctx = tmp_canvas.getContext("2d");
var img_new_width = tmp_canvas.width;
var img_new_height = tmp_canvas.height;
function zoomInCanvas() {
img_new_width *= 1.001
img_new_height *= 1.001
tmp_ctx.scale(1.001, 1.001);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tmp_canvas, -(img_new_width - canvas.width)/2, -(img_new_height - canvas.height)/2);
}
var i = 0;
const interval = setInterval(function() {
if(i == 100) {
clearInterval(interval);
}
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.drawImage(canvas, 0, 0);
requestAnimationFrame(zoomInCanvas);
i++;
}, 1000);
}
function setImageListener() {
img.onload = function () {
imgOnLoad();
};
}
$('#start').click(function() {
showSomeMedia();
});
</script>
</body>
</html>
So far I have made a moving square that when the button is clicked in the HTML file, calls the draw() function and draws a red square in the canvas area that moves accross the canvas. How do I make it so that the same function draw() can create multiple moving sqaures?
Here's the code so far:
var x = 10;
var y = 10;
function draw(){
var can = document.getElementById("myCanvas");
var ctx = can.getContext("2d");
var x = 1;
setInterval(function(){
ctx.clearRect(0,0, can.width, can.height);
ctx.fillRect(x, 20, 75, 75);
ctx.fillStyle ="red";
x=x+5;
}, 500
);
}
Not sure that my solution is good, I'm just starting to learn js, but hope it will helpful.
// variables declaration. I suggest to use Arrays
// for store individual rectangle parameters.
// rectangle start coords x and y
var rcx = [];
var rcy = [];
// delta to move x, y
var dx = [];
var dy = [];
// rectangle size (if you want it variable)
var size =[];
// init canvas
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// create and collect rectangles parameters
// on window load (here 100 rectangles created)
// with unique coords, deltas to move,
// and sizes for each rectangle.
window.onload = function() {
for (var i=0; i<100; i++) {
// in this solution all parameters randomized,
// but you can set whatever you want.
rcx[i]=(Math.floor(Math.random() * Math.floor(canvas.width)));
rcy[i]=(Math.floor(Math.random() * Math.floor(canvas.height)));
dx[i]= (Math.floor(Math.random() * Math.floor(3))-1);
dy[i]=(Math.floor(Math.random() * Math.floor(3))-1);
size[i] = (Math.floor(Math.random() * Math.floor(8)));
}};
// it is optional, but i decide
// made function for rectangle declaration.
// It will looks more compact when rendering.
function rect(x, y, size){
ctx.fillRect(x, y, size, size/2 );
ctx.fillStyle = "rgba(255,255,255,1)";
}
// finally all together into function draw()
function draw(){
setInterval(function(){
ctx.clearRect(0,0, canvas.width, canvas.height);
for (var j=0; j<100; j++) {
// read arrays
// render rectangle with params from arrays
rect(rcx[j],rcy[j],size[j]);
// add delta to move (x,y)
// and rewrite new coords to arrays
rcx[j]=rcx[j]+dx[j];
rcy[j]=rcy[j]+dy[j]};
}, 100
);
};
//rendering animation
draw();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#canvas {
width: 500px;
height: 500px;
background-color: #ccc;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="js1.js"></script>
</body>
</html>
Sorry, didn't mention about button. So for the btn changes are simple.
Create btn div in html,
Add listener on this div. Рut params in arrays if button is pushed. Instead of generation by random as it was in my solution before.
Read arrays and render all rectangles from it.
// variables declaration. I suggest to use Arrays for store individual rectangle parameters.
// rectangle start coords x and y
var rcx = [];
var rcy = [];
// delta to move x, y
var dx = [];
var dy = [];
// rectangle size (if you want it variable)
var size =[];
//counter for created rectangles
var i=0;
// init canvas
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// create and collect rectangles parameters on btn push
// with unique coords, deltas to move, and sizes for each rectangle.
var btn =document.getElementById('btn');
btn.addEventListener( 'click', function() {
//count every time you push the btn and create rect
i=i+1;
//generate rect params x,y, delta x, delta y, size
rcx[i]=20;
rcy[i]=20;
dx[i]=1
dy[i]=0
size[i] = 8;
});
// it is optional, but i decide made function for rectangle declaration. It will looks more compact when rendering.
function rect(x, y, size){
ctx.fillRect(x, y, size, size/1.5);
ctx.fillStyle = "red";
}
// finally all together into function draw()
function draw(){
setInterval(function(){
ctx.clearRect(0,0, canvas.width, canvas.height);
for (var j=1; j<rcx.length; j++) {
// read arrays
// render rectangle with params from arrays
rect(rcx[j],rcy[j],size[j]);
// add delta to move (x,y) and rewrite new coords to arrays
rcx[j]=rcx[j]+dx[j];
rcy[j]=rcy[j]+dy[j]};
}, 100
);
};
//rendering animation
draw();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
margin: 0 auto;
padding: 0;
background-color: rgb(17, 0, 28);
}
#container{
position: relative;
margin-top: 10px;
margin-left: 50px;
}
#canvas {
z-index: 0;
position:fixed;
align-self: center;
justify-self: center;
width: 80vw;
height: 50vw;
background-color: #ccc;
}
#btn {
margin: 20px 20px 20px 0px;
padding: 10px;
position:static;
top: 30px;
font-family: 'Roboto', sans-serif;
width: 65px;
background-color: brown;
cursor: pointer;
}
#btn:hover {
background-color: red;
}
#btn:active {
background-color: coral;
}
</style>
</head>
<body>
<div id="container">
<div id="btn"> Push me </div>
<canvas id="canvas"></canvas>
</div>
<script src="js1.js"></script>
</body>
</html>
The use case is for a Christmas "scratch" card, where the user needs to swipe on the image to reveal the content. When the window is resized or the phone is rotated, the canvas is redrawn. My current code is as follows:
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Division Raster</title>
<script type="text/javascript" src="wp-content/themes/generatepress_child/paper-full.min.js"></script>
<script type="text/paperscript" canvas="canvas">
// Based on 'JPEG Raster' by Jonathan Puckey:
// http://www.flickr.com/photos/puckey/3179779686/in/photostream/
// Create a raster item using the image with id='mona'
var raster = new Raster('mona');
// Make the raster invisible:
raster.visible = true;
raster.position = view.center;
var lastPos = view.center;
function moveHandler(event) {
if (lastPos.getDistance(event.point) < 1)
return;
lastPos = event.point;
var size = this.bounds.size.clone();
var isLandscape = size.width > size.height;
// If the path is in landscape orientation, we're going to
// split the path horizontally, otherwise vertically:
size /= isLandscape ? [2, 1] : [1, 2];
if (size.ceil().width > 10) {
var path = new Path.Rectangle({
point: this.bounds.topLeft.floor(),
size: size.ceil(),
onMouseMove: moveHandler
});
path.fillColor = raster.getAverageColor(path);
var path = new Path.Rectangle({
point: isLandscape
? this.bounds.topCenter.ceil()
: this.bounds.leftCenter.ceil(),
size: size.floor(),
onMouseMove: moveHandler
});
path.fillColor = raster.getAverageColor(path);
}
this.remove();
}
function onResize(event) {
project.activeLayer.removeChildren();
// Transform the raster so that it fills the bounding rectangle
// of the view:
raster.fitBounds(view.bounds, true);
// Create a path that fills the view, and fill it with
// the average color of the raster:
new Path.Rectangle({
rectangle: view.bounds,
fillColor: raster.getAverageColor(view.bounds),
onMouseMove: moveHandler
});
}
</script>
<style type="text/css" id="wp-custom-css">
#canvas{
background: center center url(/web.jpg);
width:100%;
height:100vh;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
}
#cc{
max-width:2560px;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
} </style>
</head>
<body>
<canvas id="canvas" resize></canvas>
<img width="1024" height="1024" id="mona" style="display: none;" src="/web.jpg">
</body>
</html>
Is there any way to fix the initial canvas size so the result of the "scratching" isn't lost?
Your problem resides in the onResize function which is called every time the window is resized and which basically reset your drawing.
The resize attribute on the <canvas> element also is part of the problem as it makes sure that the canvas size is updated every time the window is resized.
In your case, I think that you want to get rid of those.
Here is a fiddle adapted from your code, turning it into a static drawing that doesn't respond to resize events.
<html>
<head>
<meta charset="UTF-8">
<title>Division Raster</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.min.js"></script>
<script type="text/paperscript" canvas="canvas">
// Load image then init.
var raster = new Raster({
source: 'http://assets.paperjs.org/images/marilyn.jpg',
crossOrigin: 'anonymous',
onLoad: init
});
function init() {
// Make image fill the whole canvas.
raster.fitBounds(view.bounds, true);
var lastPos = view.center;
function moveHandler(event) {
if (lastPos.getDistance(event.point) < 1) {
return;
}
lastPos = event.point;
var size = this.bounds.size.clone();
var isLandscape = size.width > size.height;
// If the path is in landscape orientation, we're going to
// split the path horizontally, otherwise vertically:
size /= isLandscape ? [2, 1] : [1, 2];
if (size.ceil().width > 10) {
var path = new Path.Rectangle({
point: this.bounds.topLeft.floor(),
size: size.ceil(),
onMouseMove: moveHandler
});
path.fillColor = raster.getAverageColor(path);
var path = new Path.Rectangle({
point: isLandscape
? this.bounds.topCenter.ceil()
: this.bounds.leftCenter.ceil(),
size: size.floor(),
onMouseMove: moveHandler
});
path.fillColor = raster.getAverageColor(path);
}
this.remove();
}
// Create a path that fills the view, and fill it with
// the average color of the raster:
new Path.Rectangle({
rectangle: view.bounds,
fillColor: raster.getAverageColor(view.bounds),
onMouseMove: moveHandler
});
}
</script>
<style type="text/css">
canvas {
width : 100vw;
height : 100vh;
position : absolute;
top : 0;
left : 0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
Once I upload an image I make 2 clicks over it. That's how (x1,y1) and (x2,y2) are obtained. Given these 4 numbers I waanna draw a rectangle over the image by means for example of P5.js. Then I should say rect(x1,y1,x2,y2) but this never happens. How can I deal with this problem (maybe not by P5)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<button v-on:click="isHidden = false">Load img</button>
<img onclick="showCoords(event)" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>
<script>
var test = new Vue({
el: '#app',
data: {
src: ["cat.jpg", "dog.jpg"],
z: Math.round(Math.random()),
isHidden: true,
}
})
var k=0;
var koors = [];
var flag = false;
function showCoords(event) {
if (k===0){
koors[0] = event.clientX;
koors[1] = event.clientY;
k+=1;
} else if (k===1){
flag = true;
koors[2] = event.clientX;
koors[3] = event.clientY;
}
if ((koors[3] != 0) && (flag)){
console.log(koors)
}
}
//p5
function setup(){
}
function draw(){
console.log(koors[0],koors[1],koors[2],koors[3]);
rect(koors[0],koors[1],koors[2],koors[3])
}
</script>
<script src="p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<script src="js.js"></script>
</body>
</html>
P5 needs a canvas for rendering. If you don't initialize one, it creates it himself (and you are in trouble).
Also, P5 is powerful library, it has tools for events, image processing etc. For current example I wouldn't use any other library (vue).
I created canvas on top of the image (css) and rest is playing with P5.
var test = new Vue({
el: '#app',
data: {
src: [ "https://i.stack.imgur.com/XZ4V5.jpg", "https://i.stack.imgur.com/7bI1Y.jpg"],
z: Math.round(Math.random()),
isHidden: false,
}
})
var recStart;
var coords = {};
/*******************************************************************
* P5 setup
* run once, use for initialisation.
*
* Create a canvas, change dimensions to
* something meaningful(like image dim)
********************************************************************/
function setup(){
var canvas = createCanvas(480, 320);
canvas.parent('app');
}
/*******************************************************************
* P5 draw
* endless loop.
*
* Lets redraw rectangle until second click.
********************************************************************/
function draw(){
if(recStart)
drawRect();
}
/*******************************************************************
* drawRect
*
* Draw a rectangle. mouseX and mouseY are P5 variables
* holding mouse current position.
********************************************************************/
function drawRect(){
clear();
noFill();
stroke('red');
rect(coords.x, coords.y, mouseX-coords.x, mouseY-coords.y);
}
/*******************************************************************
* P5 mouseClicked
*
* P5 event. Again, mouseX and mouseY are used.
********************************************************************/
mouseClicked = function() {
if (mouseButton === LEFT) {
if(!recStart){ // start rectangle, give initial coords
coords.x = mouseX;
coords.y = mouseY;
recStart = true; // draw() starts to draw
} else {
recStart = false; // stop draw()
drawRect(); // draw final rectangle
coords = {}; // clear coords
}
}
};
canvas {
width: 500px;
height:500px;
z-index: 2;
border:1px solid;
position:absolute;
left: 0;
top: 0;
}
img {
z-index: 1;
position: absolute;
border: 2px solid black;
left: 0;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<img id="pilt" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>
It seems that you don't call draw anywhere. You may also consider draw the image into a canvas and than draw rect in this canvas. Checking if koors[3] != 0 is really risky as user may click at 0th pixel.