How to put p5.js canvas in a html div - p5.js

I am trying to add p5.js to the background of one section in my webpage. I am new to javascript and can't figure out how to bind the two parts together.

You need to add code in your setup.
Make sure you have the function in a script tag in the html as well.
Note you do not add # in the .parent().
var myCanvas = createCanvas(winWidth, winHeight);
myCanvas.parent("idnameofdiv");

if you are inserting multiple p5js canvas in one page and are already using the form new p5(sketch), you can just pass the id of your div as second parameter, like new p5(sketch, idnameofdiv)
Because the function sketch should be unique (if you don't use an IIFE), I like to put the id in the name of the sketch function as well
function sketch_idnameofdiv(p) {
p.setup = function () {
p.createCanvas(400,400);
}
p.draw = function () {
// stuff to draw
}
}
new p5(sketch_idnameofdiv, 'idnameofdiv')
if you don't need to insert multiple p5js canvas in one page, I guess you are looking for Michael Paccione's answer

P5.js gives you an html canvas that you can use for positioning your sketch.
Here is an example of using a canvas as the background of a div:
<!DOCTYPE html>
<html>
<head>
<style>
canvas {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:-1;
}
</style>
</head>
<body>
<h1>Heading</h1>
<p>paragraph 1</p>
<p>paragraph 2</p>
<script src="processing-1.4.1.min.js"></script>
<div id="canvasContainer">
<canvas data-processing-sources="rectangles.pde"></canvas>
</div>
</body>
This is Processing.js instead of P5.js, but the idea is the same. Try googling something like "html canvas as background" for a ton of results. Try something out, and post an MCVE if you get stuck.

To be more detailed about the answer:
function setup() is a function which executes ojnly once at the startup.
function draw() is a function which executes after setup() and it reloads on every frame of the picture.
The code goes like this:
<!DOCTYPE html>
<html>
<head>
<title>P5.js Example</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
<script>
function setup() {
var canvas = createCanvas(400, 400);
canvas.parent('canvasForHTML');
}
function draw() {
background(127);
}
</script>
</head>
<body>
<h1>Canvas for visualization</h1>
<div id="canvasForHTML"></div>
<p>Move your mouse around to see circles.</p>
</body>
</html>
Check this:
https://jsfiddle.net/sugandhnikhil/74Ltdy8z/1/

Related

Image not able to load when using p5js outside of online editor

I am using p5js and I am trying to load and display some images in my directory. I am trying to use the loadImage() method in my preload function to load an image. However, when I run the program, I get these errors
Fetch API cannot load file:///Users/mainuser/Documents/school/Senior/FinalProject/imgs/arms_up.png. URL scheme "file" is not supported.
🌸 p5.js says: It looks like there was a problem loading your image. Try checking if the file path (imgs/arms_up.png) is correct, hosting the file online, or running a local server. (More info at https://github.com/processing/p5.js/wiki/Local-server)
TypeError: Failed to fetch
at fetch (p5.js:28096)
at p5._main.default.loadImage (p5.js:80673)
at p5.js:62949
at preload (script.js:118)
at p5._start (p5.js:62905)
at new p5 (p5.js:63261)
at _globalInit (p5.js:62189)
My imgs folder is within the same folder as my index.html
My guess is that fetch() might need an actual URL instead of a file path.
Anybody else run into this problem? I've attached my code below (i took out irrelevant code). Thank you!
index.html
<!DOCTYPE HTML>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#1.3.1/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#teachablemachine/pose#0.8/dist/teachablemachine-pose.min.js"></script>
<script src="script.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/p5.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Pose Game</h1>
<button type="button" onclick="init()">Start Game!</button>
<button type="button" onclick="restart_game()">Restart Game</button>
<div id="main-div">
<div id="flex-div">
<div id="webcam-div">
<canvas id="canvas"></canvas>
</div>
<div id="p5-div"></div>
</div>
</div>
</body>
</html>
script.js
let arms_up_png;
let left_arm_up;
let right_arm_up;
function preload() {
arms_up_png = loadImage("imgs/arms_up.png");
}
function setup() {
var canvas = createCanvas(400, 400);
canvas.parent('p5-div');
}
function draw() {
background('green');
image(arms_up_png, 50, 50, 20, 20);
}
You are correct that fetch() will not work with local file paths, and because p5js needs to load the contents of the image file in order to display it you also cannot use local file paths with the p5js loadImage() function. In order to run your sketch locally you will need to use a local web server. The Visual Studio Code Live Server extension is quite handy for this purpose.

How to replace an image with another on button click

Hi I have a problem that I can't quite solve. I'm a total noob with HTML/Javascript, so I'm not sure how to proceed. The instructions are in the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Q2</title>
<script type="text/javascript" src="342.js"></script>
<script type="text/javascript">
function swap() {
if (Math.random()>.5){
document.getElementById("c").style.display = 'none';
document.getElementById("f").src = "images/f.jpg";
} else {
document.getElementById("d").style.display = 'none';
document.getElementById("f").src = "images/f.jpg";
}
}
</script>
</head>
<body>
<p>Add code so that clicking the button changes either the src "c.jpg" or "d.jpg" to "f.jpg" The choice of which should be replaced
should be determined randomly.</p>
<img src="images/c.jpg" id="c"><br>
<img src="images/d.jpg" id="d">
<br><br>
<button type="button" onclick="swap()">OK</button>
</body>
</html>
The original problem had everything but the scripts. When I try this, I'm able to get the image c or d to disappear, but image f doesn't appear. I don't know how to get the image to show. getELementById won't work because I haven't made an id, but how do I do that without having image f showing? Any help is appreciated.
Seems you're missing html
Try add f html element for work:
<img src="images/f.jpg" id="f">
The p tag in the html is talking about c.jpg, d.jpg and e.jpg.
Its not talking about f.jpg, you may want to check that
with the assumption that it is e.jpg and not "f.jpb". And also assuming that you have e.jpg in your images folder. Below code will work fine (small modification in the script)
function swap() {
if (Math.random()>.5){
// document.getElementById("c").style.display = 'none';
document.getElementById("c").src = "images/e.jpg";
} else {
// document.getElementById("d").style.display = 'none';
document.getElementById("d").src = "images/e.jpg";
}
}

Line spacing in CKeditor

apologies but I am an absolute noob on this. I have implemented a CKeditor on my website using the below HTML:
<!doctype html>
<html>
<head>
<!--Define the character set for the HTML element -->
<meta charset="utf-8">
<!--Call the external script to use the CDN CKEditor in your page-->
<script src="//cdn.ckeditor.com/4.6.2/standard/ckeditor.js"></script>
<script type="text/javascript">
//Define an init function that sends the rich text editor contents to the page code
function init() {
//onMessage runs when the HTML element receives a message from the page code
window.onmessage = (event) => {
if (event.data == "x") {
CKEDITOR.instances.CK1.setData( '<p></p>' );
console.log(event.data,"ok");
} else {
//postMessage sends the contents of the CKEDITOR back to the page code
window.parent.postMessage(CKEDITOR.instances.CK1.getData(),"*");
console.log(event.data,"okd");
}
}
}
</script>
</head>
<body onload="init();">
<!--Define the HTML element as a textarea-->
<textarea name="editor1" id="CK1"></textarea>
<script>
//Use the CKEditor replace() function to turn our textarea into a CKEditor rich text editor
CKEDITOR.replace("editor1");
</script>
</body>
</html>
It works great but I have a line spacing issue where it looks like there is a line in between the paragraphs, but when it displays later on it is on top of each other. Is there anyway to reduce the spacing so the user realises they need to press enter again?
Image attached, first test is 1 press of enter after text (which looks like it has a line between but doesn't), second is 2 enters.
My issue is also that I am using Wix, so I can't host the config or whatever files to change. So it all needs to be from the html link.....
Thanks!
enter image description here
These lines of code will remove extra space
:host ::ng-deep .ck-editor__editable_inline p {
margin: 0;
}
Do you need to force the user to press Enter twice for a new paragraph? If so, try this:
CKEDITOR.addCss('.cke_editable p { margin: 0 !important; }');
CKEDITOR.replace('editor1');

Thymeleaf th:inline="javascript" issue

I don't know how to solve the following: I'd like to let my Model generate real javascript dynamically based on some model logic.
This final piece of javascript code then should be added inside the $(document).ready { } part of my html page.
The thing is: If I use inline="javascript", the code gets quoted as my getter is a String (that is how it is mentioned in the Thymeleaf doc but it's not what I need ;-)
If I use inline="text" in is not quoted but all quotes are escaped instead ;-) - also nice but unusable 8)
If I try inline="none" nothing happens.
Here are the examples
My model getter created the following Javascript code.
PageHelper class
public String documentReady() {
// do some database operations to get the numbers 8,5,3,2
return "PhotoGallery.load(8,5,3,2).loadTheme(name='basic')";
}
So if I now try inline="javascript"
<script th:inline="javascript">
/*<![CDATA[*/
jQuery().ready(function(){
/*[[${pageHelper.documentReady}]]*/
});
/*]]>*/
</script>
it will be rendered to
<script>
/*<![CDATA[*/
jQuery().ready(function(){
'PhotoGallery.load(8,5,3,2).loadTheme(name=\'basic\')'
});
/*]]>*/
</script>
Which doesn't help as it is a String literal, nothing more (this is how Thymeleaf deals with it).
So if I try inline="text" instead
<script>
/*<![CDATA[*/
jQuery().ready(function(){
PhotoGallery.load(8,5,3,2).loadTheme(name='basic')
});
/*]]>*/
</script>
Which escapes the quotes.
inline="none" I do not really understand, as it does nothing
<script>
/*<![CDATA[*/
jQuery().ready(function(){
[[${pageHelper.documentReady}]]
});
/*]]>*/
</script>
To be honest I have no idea how to solve this issue and hopefully anybody out there knows how to deal with this.
Many thanks in advance
Cheers
John
I would change the approach.
Thymeleaf easily allows you to add model variables in your templates to be used in Javascript. In my implementations, I usually put those variables somewhere before the closing header tag; to ensure they're on the page once the JS loads.
I let the template decide what exactly to load, of course. If you're displaying a gallery, then render it as you would and use data attributes to define the gallery that relates to some JS code. Then write yourself a nice jQuery plugin to handle your gallery.
A relatively basic example:
Default Layout Decorator: layout/default.html
<!doctype html>
<html xmlns:layout="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org">
<head>
<title>My Example App</title>
<object th:remove="tag" th:include="fragments/scripts :: header" />
</head>
<body>
<div layout:fragment="content"></div>
<div th:remove="tag" th:replace="fragments/scripts :: footer"></div>
<div th:remove="tag" layout:fragment="footer-scripts"></div>
</body>
</html>
The thing to notice here is the inclusion of the generic footer scripts and then a layout:fragment div defined. This layout div is what we're going to use to include our jQuery plugin needed for the gallery.
File with general scripts: fragments/scripts.html
<div th:fragment="header" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: /*[[#{/}]]*/,
defaultTheme: /*[[${theme == null} ? null : ${theme}]]*/,
gallery: {
theme: /*[[${gallery == null} ? null : ${gallery.theme}]]*/,
images: /*[[${gallery == null} ? null : ${gallery.images}]]*/,
names: /*[[${gallery == null} ? null : ${gallery.names}]]*/
}
};
/*]]>*/
</script>
</div>
<div th:fragment="footer" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
</div>
In the scripts file, there are 2 fragments, which are included from the decorator. In the header fragment, a helpful context path is included for the JS layer, as well as a defaultTheme just for the hell of it. A gallery object is then defined and assigned from our model. The footer fragment loads the jQuery library and a main site JS file, again for purposes of this example.
A page with a lazy-loaded gallery: products.html
<html layout:decorator="layout/default" xmlns:layout="http://www.thymeleaf.org/" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Products Landing Page</title>
</head>
<body>
<div layout:fragment="content">
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<div th:remove="tag" layout:fragment="footer-scripts">
<script type="text/javascript" src="/js/my_gallery.js"></script>
</div>
</body>
</html>
Our products page doesn't have much on it. Using the default decorator, this page overrides the page title in the head. Our content fragment includes a title in an h1 tag and an empty div with a data-gallery attribute. This attribute is what we'll use in our jQuery plugin to initialize the gallery.
The value is set to lazyload, so our plugin knows that we need to find the image IDs in some variable set somewhere. This could have easily been empty if the only thing our plugin supports is a lazyloaded gallery.
So the layout loads some default scripts and with cleverly placed layout:fragments, you allow certain sections of the site to load libraries independent of the rest.
Here's a basic Spring controller example, to work with our app: MyController.java
#Controller
public class MyController {
#RequestMapping("/products")
public String products(Model model) {
class Gallery {
public String theme;
public int[] images;
public String[] names;
public Gallery() {
this.theme = "basic";
this.images = new int[] {8,5,3,2};
this.names = new String[] {"Hey", "\"there's\"", "foo", "bar"};
}
}
model.addAttribute("gallery", new Gallery());
return "products";
}
}
The Gallery class was tossed inline in the products method, to simplify our example here. This could easily be a service or repository of some type that returns an array of identifiers, or whatever you need.
The jQuery plugin that we created, could look something like so: my_gallery.js
(function($) {
var MyGallery = function(element) {
this.$el = $(element);
this.type = this.$el.data('gallery');
if (this.type == 'lazyload') {
this.initLazyLoadedGallery();
}
};
MyGallery.prototype.initLazyLoadedGallery = function() {
// do some gallery loading magic here
// check the variables we loaded in our header
if (MY_APP.gallery.images.length) {
// we have images... sweet! let's fetch them and then do something cool.
PhotoGallery.load(MY_APP.gallery.images).loadTheme({
name: MY_APP.gallery.theme
});
// or if load() requires separate params
var imgs = MY_APP.gallery.images;
PhotoGallery.load(imgs[0],imgs[1],imgs[2],imgs[3]).loadTheme({
name: MY_APP.gallery.theme
});
}
};
// the plugin definition
$.fn.myGallery = function() {
return this.each(function() {
if (!$.data(this, 'myGallery')) {
$.data(this, 'myGallery', new MyGallery(this));
}
});
};
// initialize our gallery on all elements that have that data-gallery attribute
$('[data-gallery]').myGallery();
}(jQuery));
The final rendering of the products page would look like so:
<!doctype html>
<html>
<head>
<title>Products Landing Page</title>
<script type="text/javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: '/',
defaultTheme: null,
gallery: {
theme: 'basic',
images: [8,5,3,2],
names: ['Hey','\"there\'s\"','foo','bar']
}
};
/*]]>*/
</script>
</head>
<body>
<div>
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
<script type="text/javascript" src="/js/my_gallery.js"></script>
</body>
</html>
As you can see, Thymeleaf does a pretty good job of translating your model to valid JS and actually adds the quotes where needed and escapes them as well. Once the page finishes rendering, with the jQuery plugin at the end of the file, everything needed to initialize the gallery should be loaded and ready to go.
This is not a perfect example, but I think it's a pretty straight-forward design pattern for a web app.
instead of ${pageHelper.documentReady} use ${pageHelper.documentReady}

Is it possible generated from local file image from html5-canvas

My canvas has image which programly generated from local file or from images from internet. When I try to save it using toDataURl function I get secure error. How can I save result (without server, using only js ) and is it possible?
I know about security rule but maybe there is some solution to bypass this rule
All my code is in github if need
Shame! Don't bypass rules built to provide security for our users.
The key to satisfying CORS security and still getting what you need is to let the user select the image file you need to load into canvas.
If the user selects the file, CORS security is satisfied and you can use the canvas as you need (including using canvas.toDataURL to save the canvas).
Here are the steps to let a user select a file from their local drive:
Add an html input element with type="file"
The user clicks browse on this element and selects their file
When the user clicks OK, use window.URL.createObjectURL to create a URL from their selected file.
Create a new Image and set its source to the URL you created in #3.
Use context.drawImage to draw your new image on the canvas.
The resulting canvas is CORS compliant so canvas.toDataURL will work.
Here's example code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
$("#fileInput").change(function(e){
var URL = window.webkitURL || window.URL;
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
canvas.width=img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0);
ctx.fillStyle="black";
ctx.fillRect(0,canvas.height-30,canvas.width,30);
ctx.fillStyle="white";
ctx.font="18px verdana";
ctx.fillText("I'm OK with CORS!",5,canvas.height-8);
}
img.src = url;
});
$("#save").click(function(){
var html="<p>Right-click on image below and Save-Picture-As</p>";
html+="<img src='"+canvas.toDataURL()+"' alt='from canvas'/>";
var tab=window.open();
tab.document.write(html);
});
}); // end $(function(){});
</script>
</head>
<body>
<input type="file" id="fileInput">
<button id="save">Save</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Resources