I am trying to get the processing code from textbox and make it running in canvas but i don't know what is happening can someone help me? When i debug it's says ctx.compile(); is not a function how can i make it work propperly? Here is the code i use.
<!DOCTYPE Html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles/style2.css" >
<script src="processing-1.4.1.js"></script>
<script type="text/javascript">
function submitTryit() {
var text = document.getElementById("textareaCode").value;
var ifr = document.createElement("iframe");
ifr.setAttribute("frameborder", "0");
ifr.setAttribute("id", "iframeResult");
document.getElementById("iframewrapper").innerHTML = "";
document.getElementById("iframewrapper").appendChild(ifr);
var ifrw = (ifr.contentWindow) ? ifr.contentWindow : (ifr.contentDocument.document) ? ifr.contentDocument.document : ifr.contentDocument;
ifrw.document.open();
ifrw.document.write(text);
ifrw.document.close();
canvas();
if (ifrw.document.body && !ifrw.document.body.isContentEditable) {
ifrw.document.body.contentEditable = true;
ifrw.document.body.contentEditable = false;
}
function canvas() {
var ifrr = document.getElementById('iframeResult');
var iframediv = (ifrr.contentWindow.document) ? ifrr.contentWindow.document : (ifrr.contentDocument.document) ? ifrr.contentDocument.document : ifrr.contentDocument;
var canv = document.createElement('CANVAS');
canv.setAttribute('id', 'mycanvas');
var ctx = canv.getContext("2d");
ctx.compile();
iframediv.body.appendChild(canv);
}
}
function compile(){
var processingCode = document.getElementById('textCode').value;
var jsCode = Processing.compile(processingCode).sourceCode;
}
</script>
</head>
<body>
<div class="container">
<!--Iframe-->
<div class="iframecontainer">
<div id="iframewrapper" class="iframewrapper">
</div>
</div>
<!--PJS text field-->
<div class="PJStextwraper">
<div class="overPJStext">
</div>
<textarea id="textCode" spellcheck="false" autocomplete="off" wrap="logical"> int x,y,w;
float vx,vy;
void setup() {
size(300,200);
x = int(random(width));
y = int(random(height));
vx = random(5);
vy = random(5);
w = int(10+random(10));
}
void draw() {
background(140,70,60);
ellipse(x,y,w,w);
x += vx;
y += vy;
//
if(x > width || x < 0) {
vx *= -1;
}
if(y > height || y < 0) {
vy *= -1;
}
}
</textarea>
</div>
<button class="BT" type="button" onclick="submitTryit()">Run ยป</button>
</div> <!-- End container-->
</body>
</html>
The error "ctx.compile(); is not a function" is expected since you are trying to call a function that does not exist on the 2d canvas context. If I understand correctly, you are trying to run your own compile function and render it on the canvas you just created.
To do so, you need to change a few things, try the following and see if it works:
function canvas() {
var ifrr = document.getElementById('iframeResult');
var iframediv = (ifrr.contentWindow.document) ? ifrr.contentWindow.document : (ifrr.contentDocument.document) ? ifrr.contentDocument.document : ifrr.contentDocument;
var canv = document.createElement('canvas');
canv.setAttribute('id', 'mycanvas');
// The ctx will be created in an instance of Processing.
// So no need for the following line.
// var ctx = canv.getContext("2d");
compile(canv);
iframediv.body.appendChild(canv);
}
// Here you can pass the canvas where you want to render the code.
function compile(canv) {
var processingCode = document.getElementById('textCode').value;
var jsCode = Processing.compile(processingCode).sourceCode;
// Now that you have the code in JS, you can create an instance of Processing.
// But, what you get from the compiler is a string,
// so you need to convert the string to JS.
// For instance, I use here eval(jsCode)
var processingInstance = new Processing(canv, eval(jsCode));
}
Related
I have a simple html that has multiple div elements.
<body onload="start()">
<div id="image1"></div>
<div id="image2"></div>
</body>
onload event of the body triggers a javascript function called start() that creates two objects from a class called img. The class creates a canvas in the div that it points to (the first parameter) with a width and height stated in the second and third parameters.
function start(){
let img1 = new img("image1",640,480);
let img2 = new img("image2",320,240);
}
The following class creates the canvas and an array which it fills with random numbers between 0-255. It also adds a mousemove event to the object.
class img{
constructor(p_divid, p_w, p_h){
this.divid = p_divid; //DIV id
this.w = p_w; //width of the div
this.h = p_h; //height of the div
this.pixels = []; //pixel values
for (let index = 0; index < this.w*this.h; index++) {
this.pixels[index] = Math.floor(Math.random()*255); //a random value up to 255
}
this.div = document.getElementById(this.divid); //div element
this.div.innerHTML = "<canvas id='canvas-"+this.divid+"' width='"+this.w+"' height='"+this.h+"' style='background-color:red;'></canvas>"; //this creates a canvas
this.canvas = document.getElementById("canvas-"+this.divid); //canvas element
this.canvas.addEventListener("mousemove", this.mmove); //mouse move event
}
the mousemove event gets the coordinates of the mouse relative to the element and calculates the position of the element that it wants to reach in the object's pixels. I want to learn the best practice to reach the objects pixels array.
mmove(e){
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
var position_in_array = (y * 640) + x;
//******************************************************************************
//THIS IS WHERE I WOULD LIKE TO GET THE VALUE OF THE PIXELS ARRAY AND
//WRITE IT ON THE CONSOLE. Something like:
//let x = object.pixels[position_in_array];
//******************************************************************************
}
the whole html file that you see above is :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test</title>
</head>
<body onload="start()">
<div id="image1"></div>
<div id="image2"></div>
</body>
<script>
function start(){
let img1 = new img("image1",640,480);
let img2 = new img("image2",320,240);
}
class img{
constructor(p_divid, p_w, p_h){
this.divid = p_divid; //DIV id
this.w = p_w; //width of the div
this.h = p_h; //height of the div
this.pixels = []; //pixel values
for (let index = 0; index < this.w*this.h; index++) {
this.pixels[index] = Math.floor(Math.random()*255); //a random value up to 255
}
console.log(this.pixels);
this.div = document.getElementById(this.divid); //div element
this.div.innerHTML = "<canvas id='canvas-"+this.divid+"' width='"+this.w+"' height='"+this.h+"' style='background-color:red;'></canvas>"; //this creates a canvas
this.canvas = document.getElementById("canvas-"+this.divid); //canvas element
this.canvas.addEventListener("mousemove", this.mmove); //mouse move event
}
mmove(e){
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
var position_in_array = (y * 640) + x;
//******************************************************************************
//THIS IS WHERE I WOULD LIKE TO GET THE VALUE OF THE PIXELS ARRAY AND
//WRITE IT ON THE CONSOLE. Something like:
//let x = object.pixels[position_in_array];
//******************************************************************************
}
}
</script>
</html>
You can used bind method to pass extra arguments like
this.mmove.bind(null,this.pixels);
mmove(pixels, e){
Here is an example code on how you can pass extra argument with bind
document.querySelector("#btn").addEventListener('click', a.bind(null,12));
function a(v,e){
alert(e.target.textContent);
alert(v);
}
<button id="btn">Click</button>
Thanks to 'charlietfl' for pointing me to the right direction.
changing my addeventlistener line to :
this.canvas.addEventListener("mousemove", this.mmove.bind(this));
and the mmove function to
mmove(e){
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
var position_in_array = (y * 640) + x;
let value = this.pixels[position_in_array];
console.log(value);
}
solved my problem.
I've been attempting to create a ecology simulation and so far its been going good. The code below does work I'm just wondering if theres an easier way to draw more items on the canvas with code instead of manually doing it. The way I'm doing it makes me consider the lag because I will be adding a lot to the code (e.g. move, detected, reproduce, chase, run, etc). Thank you for seeing this
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
spawnWolves();
spawnWolves();
spawnWolves();
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
Your solution seems very complicated ...
Please, take a look at the following code.
<!DOCTYPE html>
<html>
<title>AI spawn test</title>
<canvas id="canvas" width="110" height="110"></canvas>
<script>
var ctx = canvas.getContext("2d");
var drawRect=function(rects){
for (var i=1; i<=rects; i++){
var rand3=Math.floor(Math.random() * 100) + 1;
var rand4=Math.floor(Math.random() * 100) + 1;
ctx.fillStyle='red';
ctx.fillRect(rand3, rand4, 10, 10)
}
}
drawRect(20);
</script>
This type of 'replication' is done by using loop. There are several loop types, but their explanation is too broad. You can browse the net.
I gave you 2 examples below - with for loop and with while loop.
//This tag will regulate the spawning of new sheep/wolves
var totalWolves = 0;
var totalSheep = 0;
var canavs = document.getElementById("canvas");
var body = document.getElementById("body");
//styler
body.style.overflow = "hidden";
body.style.margin = "0px";
canvas.style.backgroundColor = "black";
function spawnWolves(){
totalWolves++;
var name = "wolf" + totalWolves;
var scrpt = document.createElement("SCRIPT");
document.body.appendChild(scrpt);
scrpt.setAttribute("id", name);
var script = document.getElementById(name);
script.innerHTML = "var rand3 = Math.floor(Math.random() * 100) + 1; var rand4 = Math.floor(Math.random() * 100) + 1; var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.fillStyle = 'red'; context.fillRect(rand3, rand4, 10, 10); context.fill();";
}
for(var i=0; i<12; i++)
{
spawnWolves();
}
var maxWolves=9;
while(totalWolves < maxWolves)
{
spawnWolves();
}
<!DOCTYPE html>
<html>
<head>
<title>AI spawn test</title>
</head>
<body id="body">
<canvas id="canvas" width="1366px" height="768px"/>
<script>
</script>
</body>
</html>
The first loop will run until its internal counter i goes from 0 to 12 and will call the function exactly 12 times.
The second loop will run as long as the condition totalWolves < maxWolves is true. totalWolves is your counter you increase in your function and maxWolves is the limit when you want the loop to stop.
Because these 2 examples are added here one after another the second wont work. After the first one executes you will already have 12 wolves and the second loop will not enter because 12 < 9 is false.
Page for Example:
http://google.com/recaptcha/api2/demo
If i open the image 'myid' the frame will be - EXAMPLE:frame2
now what i want to do, is to draw canvas of 'myid' inside the 'frame2'.
here is the code that i have: (draw by element id)
var canvas = window.document.createElementNS('http://www.w3.org/1999/xhtml', 'html:canvas');
var selection_element = window.document.getElementById("myid");
var selection;
var de = window.document.documentElement;
var box = selection_element.getBoundingClientRect();
var new_top = box.top + window.pageYOffset - de.clientTop;
var new_left = box.left + window.pageXOffset - de.clientLeft;
var new_height = selection_element.offsetHeight;
var new_width = selection_element.offsetWidth;
selection={
top:new_top,
left:new_left,
width:new_width,
height:new_height,
};
canvas.height = selection.height;
canvas.width = selection.width;
var context = canvas.getContext('2d');
context.drawWindow(
window,
selection.left,
selection.top,
selection.width,
selection.height,
'rgba(255, 255, 255, 0)'
);
var canvasdata = canvas.toDataURL('','').split(',')[1];
To append item to frame you need to call that by id. In this HTML:
<iframe id="frm1"></iframe>
<iframe id="frm2"></iframe>
If you use this code:
$(document).ready(function ()
{
var frames = window.frames;
for (var i = 0; i < frames.length; i++)
{
var fi = frames[i]
$(fi).load(function ()
{
$(this).contents().find('body').append("<span>Hello World!</span>");
});
}
});
Does not work, But this one works:
<html>
<head>
<title></title>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
</head>
<body>
<iframe id="frm1"></iframe>
<iframe id="frm2"></iframe>
<script>
$(document).ready(function ()
{
var frm1 = window.frames["frm1"];
$(frm1).load(function ()
{
$(frm1).contents().find('body').append("<span>Hello World!</span>");
});
});
</script>
</body></html>
I tried to create a code snippet, but it seems it has problem with frames.
You can copy the exact HTML and test that.
So for a school assignment I need to make a javascript module/small lib. so I'm making something that wil skew panels on mouse out. But something keeps going wrong. This is the code I've got;
var panels = (function () {
var ANGLE = 45;
var skewPanels = document.querySelectorAll(".skewPanel");
var colors = ['#4975FB', '#924DE6', '#EF5252', '#F59500'];
for (var i = 0; i < skewPanels; i++) {
floatable(skewPanels[i], colors[i]);
}
function floatable (panel, color) {
let content = panel.querySelector(".content");
content.style.backgroundColor = color;
panel.addEventListener('mouseout', e => {
content.style.transform = `perspective(300px)
rotateY(0deg)
rotateX(0deg)`;
});
panel.addEventListener('mouseout', e => {
var w = panel.clientWidth;
var h = panel.clientHeight;
var y = (e.offsetX - w * 0.5) / w * ANGLE;
var x = (1 - (e.offsetY - h * 0.5)) / h * ANGLE;
content.style.transform = `perspective(300px)
rotateX(${x}deg)
rotateY(${y}deg)`;
});
}
return {
floatable: floatable
}
})();
This is the html code.
<div class="skewPanel">
<div class="content">HOVER</div>
</div>
<div class="skewPanel">
<div class="content">HOVER</div>
</div>
<div class="skewPanel">
<div class="content">HOVER</div>
</div>
<div class="skewPanel">
<div class="content">HOVER</div>
</div>
<script type="text/javascript">
panels.floatable();
</script>
So I keep getting the error "Cannot read property 'querySelector' of undefined". I don't understand why this error comes up, I am giving it the div to find look for ".content". I got it working in non-modular style, but now it keeps breaking on me. Could someone explain to me what I'm doing wrong?
Ok so I'm attempting to have a webpage with two buttons. Each of these buttons, when clicked, creates a new canvas and calls a different draw function. The first draw function would draw large circles where the users mouse is and small ones when the mouse is pressed. The other draw function does the same thing except small circles when the mouse is unpressed and large ones when it is. I'm not having a problem referencing one of these with the button but the other button doesn't seem to call its draw function. sketch2.js seems to be working fine but it seems that the draw function in sketch.js is not being called. Any advice on how I should go about fixing this is greatly appreciated!
Below is my HTML code:
<html>
<head>
<meta charset="UTF-8">
<button id="myBtn">little then big</button>
<div id="holder"></div>
<button id="myBtn2">big then little</button>
<div id="holder2"></div>
<style> body {padding: 0; margin:0;} </style>
</head>
<body>
<script type="text/javascript" src = "/Users/bburke95/Desktop/JS/p5.dom.js"> </script>
<script language="javascript" type="text/javascript" src="../p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="sketch2.js"></script>
</body>
</html>
This is my sketch.js class
btn = document.getElementById("myBtn");
var q;
btn.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder").innerHTML = '<canvas id="myCanvas" width="490" height="220"></canvas>';
q = 1;
set = 0;
}
function draw() {
if (q == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(255);
x = 160;
y = 160;
} else {
fill(0);
x = 80;
y = 80;
}
ellipse(mouseX, mouseY, x, y);
}
}
and this is my sketch2.js class
btn2 = document.getElementById("myBtn2");
var set;
btn2.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder2").innerHTML = '<canvas id="myCanvas2" width="490" height="220"></canvas>';
set = 1;
q = 0;
}
function draw() {
if (set == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(0);
x = 80;
y = 80;
} else {
fill(255);
x = 160;
y = 160;
}
ellipse(mouseX, mouseY, x, y);
}
}
If you want to run more than one P5.js processing sketches on the same page, you have to use "instance mode" to ensure that all the functions aren't cluttering the global namespace (which is a good idea anyway) so they don't overwrite one another.
From their Github project, you can instantiate new sketches like this:
var s = function( p ) {
var x = 100;
var y = 100;
p.setup = function() {
p.createCanvas(700, 410);
};
p.draw = function() {
p.background(0);
p.fill(255);
p.rect(x,y,50,50);
};
};
var myp5 = new p5(s);