Polymer Element Error by displaying Image inside FabricJS Canvas - javascript

I'm trying to display an Image on the FabricJS Canvas inside my Polymer Element. By doing this, this error appears:
Uncaught TypeError: Cannot read property '_set' of undefined
at klass._onObjectAdded (fabric.js:6964)
at klass.add (fabric.js:260)
at HTMLElement.ready (convert-section.html:97)
at HTMLElement._enableProperties (property-accessors.html:531)
at HTMLElement.connectedCallback (element-mixin.html:630)
at HTMLElement._attachDom (element-mixin.html:690)
at HTMLElement._readyClients (element-mixin.html:663)
at HTMLElement._flushClients (property-effects.html:1518)
at HTMLElement._propertiesChanged (property-effects.html:1644)
at HTMLElement._flushProperties (property-accessors.html:549)
Is it possible to display an Image on a FabricJs canvas inside my Polymer Element? Or did I made an misstake? I'm new to Polymer and I don't have much experience.
I can display shapes like triangles etc.
Here is my Element:
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="my-paper-element-styles.html">
<dom-module id="convert-section">
<template>
<style include="my-paper-element-styles">
</style>
<canvas id="convertCanvas" ></canvas>
</template>
<script>
class ConvertSection extends Polymer.Element {
static get is() {
return 'convert-section';
}
static get properties() {
return {
imageLocationPath: {
type: String,
notify: true
}
};
}
disconnectedCallback() {
super.disconnectedCallback();
this.imageLocationPath = "";
}
ready() {
super.ready();
this.canvas = this.__canvas = new fabric.Canvas(this.$.convertCanvas);
var height = window.innerHeight - 48;
var width = window.innerWidth - 300;
this.canvas.setHeight(height);
this.canvas.setWidth(width);
var image = fabric.Image.fromURL('img/viper-board.png');
this.canvas.add(image);
}
}
window.customElements.define(ConvertSection.is, ConvertSection);
</script>
<script src="../../node_modules/fabric/dist/fabric.js"></script>
</dom-module>

ready() {
super.ready();
var self = this;
self.canvas = self.__canvas = new fabric.Canvas(self.$.convertCanvas);
var height = window.innerHeight - 48;
var width = window.innerWidth - 300;
self.canvas.setHeight(height);
self.canvas.setWidth(width);
fabric.Image.fromURL('img/viper-board.png',function(oImg){
oImg.set({
left:10,
top:10
});
self.canvas.add(oImg);
});
}
As you can see fromURL doesn't return anything. You need to pass source url and a callback function and add that image inside callback function.

Related

How to extend the canvas to the size of the parent div with P5JS?

I want to add my canvas inside a specific div and I want it to be as big as the canvas size.
For example on this code I would like the canvas to be inside the div "p5-div" and to be as big as it is. Having in consideration that the size of the div is unpredictable because is set by css and this can change.
<!doctype html>
<html lang="en">
<head>
<style>
#p5-div {
width: 50%;
height: 300px
}
</style>
</head>
<body>
<h1>My Sketch</h1>
<div id="p5-div">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js" integrity="sha512-NxocnqsXP3zm0Xb42zqVMvjQIktKEpTIbCXXyhBPxqGZHqhcOXHs4pXI/GoZ8lE+2NJONRifuBpi9DxC58L0Lw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
function setup() {
createCanvas(100, 100); // this has to be adapted in load time to the side of the div
}
function draw(){
background(33);
}
</script>
</body>
</html>
To allocate your canvas inside an specific div you have to use this code in your setup():
function setup() {
const myCanvas = createCanvas(divWidth, divHeight);
myCanvas.parent("div-id");
}
Now, in order to know the size of the canvas it gets a bit more complicated, this is my solution:
class Utils {
// Calculate the Width in pixels of a Dom element
static elementWidth(element) {
return (
element.clientWidth -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-left")) -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-right"))
)
}
// Calculate the Height in pixels of a Dom element
static elementHeight(element) {
return (
element.clientHeight -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-top")) -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-bottom"))
)
}
}
Then we can do:
function setup() {
p5Div = document.getElementById("div-id");
const p5Canvas = createCanvas(Utils.elementWidth(p5Div), Utils.elementHeight(p5Div));
p5Canvas.parent(p5Div);
}

Working with ReactJS and HTML5 Canvas

I have a root component that renders <Particle /> components and <Particle /> component render function is:
render: function(){
var data = this.props.data,
canvas = document.createElement('canvas'),
context;
canvas.style.position = 'absolute';
canvas.style.top = data.y + 'px';
canvas.style.left = data.x + 'px';
context = canvas.getContext('2d');
context.drawImage(data.img, data.x, data.y, data.tileSize, data.tileSize, 0, 0, data.tileSize, data.tileSize);
return canvas;
}
And this returns the following error:
Uncaught Error: Invariant Violation: Particle.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
I had a look at Flipboard's react-canvas but I couldn't find any good examples similar to my situation.
So any help would be much appreciated.
You should just return a single canvas element with a reference to it. This element is not the same as a DOM node; React transforms it into a React Component using JSX:
render: function() {
return <canvas ref="canvas" />
}
Then modify it inside a lifecycle method:
componentWillReceiveProps: function() {
var canvas = React.findDOMNode(this.refs.canvas);
canvas.style.position = 'absolute';
// etc ...
}
You could also set some inline style attributes inside the render:
render: function() {
var styles = {
position: 'absolute',
top: this.props.data.y,
left: this.props.data.x
}
return <canvas ref="canvas" style={styles} />
}
...but the context/drawimage would be best to put in a lifecycle method since you need access to the dom node.

React.JS calculating img width in virtual DOM

I'm trying to find the width of an <img> to center it via JavaScript.
Trying to calculate the width of this react.js DOM node returns 0.
var Player = React.createClass({
componentDidMount:function(){
var imgEl = this.refs.imgSize.getDOMNode();
console.log(imgEl.offsetWidth);
},
render: function () {
return (
<img ref="imgSize" src={this.props.imageURL} />
);
}
});
You could use the image's onLoad event to make sure it's loaded before you try this:
<script src="http://fb.me/react-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
<script type="text/jsx;harmony=true">void function() { "use strict";
var Player = React.createClass({
_onLoad(e) {
console.log(e.target.offsetWidth)
},
render() {
return <img src={this.props.imageURL} onLoad={this._onLoad}/>
}
})
React.render(<Player imageURL="http://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg"/>, document.body)
}()</script>
I wrote a React library that exposes a size object (with width and height props) to your components.
You can use it like so for your use case:
var SizeMe = require('react-sizeme');
var Player = React.createClass({
componentDidMount:function(){
var imgEl = this.refs.imgSize.getDOMNode();
console.log(imgEl.offsetWidth);
},
render: function () {
// height and width via props!!
var width = this.props.width;
var height = this.props.height;
return (
<img ref="imgSize" src={this.props.imageURL} />
);
}
});
// Wrap your component with the SizeMe HOC!
module.exports = SizeMe()(Player);
Demo: https://react-sizeme-example-esbefmsitg.now.sh/
Github: https://github.com/ctrlplusb/react-sizeme

How to detect onload event of image which was loaded in custom object

I am creating a sample program to display an image on canvas but would like to enclose actual drawing process into a custom object.
The following code won't show the image as pictFrame.img.onload can't catch onload event of image file. Chrome console says "TypeError: Cannot set property 'onload' of undefined" with the expression although it can correctly evaluate pictFrame.img.src or pictFrame.img.height.
How should I detect image loading which is being initiated when the object is created?
<html>
<head>
<script type="text/javascript">
function pictFrame(context, imgsrc, pos_x, pos_y, size_x, size_y)
{
this.context = context;
this.img = new Image();
this.img.src = imgsrc;
this.pos_x = pos_x;
this.pos_y = pos_y;
this.size_x = size_x;
this.size_y = size_y;
this.draw = function() {
this.context.drawImage(this.img, this.pos_x, this.pos_y, this.size_x, this.size_y);
};
}
// These variables must live while the page is being displayed.
// Therefore, they can't be defined within window.onload function.
var canvas;
var context;
var pictFrame;
window.onload = function()
{
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
pictFrame = new pictFrame(context, "darwin.jpg", 10, 10, 200, 200);
};
pictFrame.img.onload = function() // Can't catch onload event
{
pictFrame.draw();
}
</script>
</head>
<body>
<canvas id="canvas" width="500" height="300"></canvas>
</body>
</html>
Its because you are calling before pictFrame gets instantiated. You get this in chrome,
Uncaught TypeError: Cannot set property 'onload' of undefined
do like below instead,
window.onload = function()
{
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
pictFrame = new pictFrame(context, "images/bahu.png", 10, 10, 200, 200);
console.log("called");
pictFrame.img.onload = function()
{
console.log(" onload called");
pictFrame.draw();
}
};
I mean, do onload call after window.onload has finished instead of calling it before.

Autoscaling an svg on window resize

I have this code:
function myClient() {
if (!(this instanceof arguments.callee)) {
return new arguments.callee(arguments);
}
var self = this;
this.init = function() {
self.viewResized();
self.drawSvg();
};
this.viewResized = function () {
var width = $('body').width(),
windowHeight = $(window).height(),
svgCanvasHeight = width * (369.0 / 567.0);
$('#svg').css({
'margin-top': 10
});
}
this.drawSvg = function() {
// ...
}
var myClient;
jQuery(function() {
myClient = new myClient();
$(window).resize(function() {
console.log("window resized");
myClient.viewResized();
});
});
How do I get the svgCanvasHeight in drawSvg dynamically so that when the window is resized, so does the svg's viewBox and svg?
Answered here: Get the real size of a SVG/G element
With regards to viewBox:
I have had a lot of problems with SVG and jQuery.
While html attributes are case-insensitive the svg ones (like viewBox) aren't. I'd try using the element.setAttribute(name, value) native JS function. This worked for me, and make sure you're using viewBox with the capital B.

Categories

Resources