How to expose ctx from inside Webcomponent? - javascript

When I try to set the width and height of the canvas element in the draw function, it seems to be setting them on some canvas, but not the one I'm looking at. Upon inspection of the canvas with the border I defined in the webcomponent, you will see that it still has the standard dimensions instead of being resized.
I'd like to expose the ctx of the component for use outside of it. What am I doing wrong?
class Component extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
const canvasContainer = document.createElement('div');
canvasContainer.classList.add('canvas-container')
canvasContainer.innerHTML = `
<style>
.canvas-container {
width: 100%;
height: 100%;
}
canvas {
border: 1px solid black;
}
</style>
<canvas></canvas>
`;
this.shadow.appendChild(canvasContainer);
}
get ctx () {
return this.shadow.querySelector('canvas').getContext('2d');
}
}
customElements.define('canvas-component', Component);
const component = new Component();
const ctx = component.ctx;
const canvas = component.ctx.canvas;
const draw = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
console.log(canvas);
window.requestAnimationFrame(draw);
}
draw();
html, body {
width: 100%;
height: 100%;
margin: 0;
}
<canvas-component></canvas-component>

repeating comment:
Why const component = new Component(); and not work with the
in the DOM? Those are 2 different objects and only
the latter is visible on your screen (which you do NOT change the size
of)
And you can shorten that code to:
<script>
customElements.define('canvas-component', class Component extends HTMLElement {
constructor() {
super().attachShadow({mode:'open'}).innerHTML = `
<style>canvas { width:100%;height:100%; border:1px solid black }</style>
<canvas></canvas>`;
}
get ctx(){
return this.shadowRoot.querySelector('canvas').getContext('2d');
}
size(w, h) {// also clears the whole canvas
this.ctx.canvas.width = w; this.ctx.canvas.height = h;
}
rect({x=10,y=x,w=20,h=w,l=2,c='red'}){
this.ctx.lineWidth = l;
this.ctx.strokeStyle = c;
this.ctx.strokeRect( x, y, w, h );
}
});
</script>
<canvas-component id="C1"></canvas-component>
<script>
onload = () => {
C1.size(innerWidth, innerHeight);
C1.rect({});
C1.rect({x:80,w:50});
C1.rect({x:50,w:150,c:'green',l:3});
}
</script>

Related

Image in Canvas get cropped only on chrome

I am using PIXIjs to draw and modify large size Image! for large size image the image get cropped as following:
but on firefox is totally okay:
I saw something as following on DEVtool-chrome that I think it might be reason for this and tried to override this but does not work:
I would like to have the full image as firefox on chrome as well!
here is js:
private drawImage(): void {
PIXI.Loader.shared.reset();
const frame = document.querySelector('#frame');
const url = this.urlInputImage;
this.removeAllChildNodes(frame);
const app = new PIXI.Application({
backgroundColor: 0xffffff,
});
const container = new PIXI.Container();
app.stage.interactive = true;
app.stage.on('rightclick', e =>{
this.contextmenuClick.emit(e);
this.rightClick(e);
});
const graphics = new PIXI.Graphics();
this.detectedPositions.forEach((detectedInfo) => {
const boundingBox = detectedInfo['boundingBox'];
graphics.lineStyle(/*border width*/5,/*border color*/ PIXI.utils.string2hex(detectedInfo['detectionBoxesHexColor']), 1);
const points = Object.keys(boundingBox).map(function(boundingBoxIndex){
return boundingBox[boundingBoxIndex];
});
const pointsFiltered = points.filter((point) => {
return point !== null;
});
graphics.drawPolygon(pointsFiltered);
graphics.endFill();
});
PIXI.Loader.shared
.add('layout',url)
.load(setup);
function setup() {
const pic = new PIXI.Sprite(PIXI.Loader.shared.resources.layout.texture);
const border = new PIXI.Graphics();
const borderWidth = 5;
const borderColor = 1261722;
border.lineStyle(borderWidth, borderColor);
border.drawRect(app.stage.x , app.stage.y , pic.width , pic.height );
container.addChild(pic);
container.addChild(border);
container.addChild(graphics);
app.stage.addChild(container);
const w = pic.width;
const h = pic.height;
app.renderer.view.style.width = w + "px";
app.renderer.view.style.height = h + "px";
//this part adjusts the ratio:
app.renderer.resize(w, h);
}
frame.appendChild(app.view);
PIXI.BaseTexture.removeFromCache('layout');
}
here is the css:
:host {
display: block;
}
canvas {
background-color: white;
}
#frame {
overflow: auto;
background-color: white;
height: 450px;
width: auto;
}`
here is html
<div id="frame"></div>

How do I get the code in jsfiddle to work in my Visual Studio Code?

const canvasEle = document.getElementById('drawing-container');
const canvasPad = document.getElementById('pad');
const toolbar = document.getElementById('toolbar');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
const canvasOffsetX = canvas.offsetLeft;
const canvasOffsetY = canvas.offsetTop;
canvas.width = window.innerWidth - canvasOffsetX;
canvas.height = window.innerHeight - canvasOffsetY;
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
toolbar.addEventListener('click', e => {
if (e.target.id === 'clear') {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
});
toolbar.addEventListener('change', e => {
if(e.target.id === 'stroke') {
ctx.strokeStyle = e.target.value;
}
if(e.target.id === 'lineWidth') {
lineWidth = e.target.value;
}
});
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
color: white;
}
h1 {
background: #7F7FD5;
background: -webkit-linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
background: linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.cnv-wrapper {
height: 100%;
display: flex;
}
.pad {
height: 100%;
display: flex;
border: 4px solid #333;
}
.container {
height: 100%;
display: flex;
}
#toolbar {
display: flex;
flex-direction: column;
padding: 5px;
width: 70px;
background-color: #202020;
}
#toolbar * {
margin-bottom: 6px;
}
#toolbar label {
font-size: 12px;
}
#toolbar input {
width: 100%;
}
#toolbar button {
background-color: #1565c0;
border: none;
border-radius: 4px;
color:white;
padding: 2px;
}
<!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 = 0.1">
<link rel = "stylesheet" href = "styles.css">
<title> Pipe Illustrator </title>
</head>
<body>
<section class = "container">
<div id = "toolbar">
<h1>Draw.</h1>
<label for="stroke">Stroke</label>
<input id="stroke" name='stroke' type="color">
<label for="lineWidth">Line Width</label>
<input id="lineWidth" name='lineWidth' type="number" value="5">
<button id="clear">Clear</button>
</div>
<div class = "drawing-container">
<canvas id = "drawing-container"></canvas>
</div>
<div class = "cnv-wrapper">
<canvas id = "cnv-wrapper"></canvas>
</div>
</section>
<script src = "./index.js"></script>
</body>
</html>
The project is to make a simple line drawer which makes allows me to draw fixed straight lines without the previous line being removed. The code written below is exactly what I need and was provided by another user from a question I asked previously about making it as my code wouldn't allow for the previous line to remain when drawing a new one.
This is the code below which is in jsfiddle, when I copy and paste it into my Visual studio code, I don't get the same output as I would in jsfiddle, the canvas doesn't appear nor does it allow anything to be drawn. Am I missing something ?
Right so this is the code i have written in VSC. It isn't entirely what was in the jsfiddle, i tried to integrate some other functions from another paint project i did. I was trying to add a toolbar for line colour and width. I think the way i have written it is contradicting it all got quite messy and was quite a fail. These are projects im doing to learn code as i am still a beginner to coding. Thank you for your help and input.
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>
From comments where I advise:
You can't just copy and paste code [from fiddle] without also using the appropriate html tags. Your CSS needs to go in style tags. Your scripts need to go in script tags. The dom elements, e.g. the "canvas" needs to go in the body tag. Etc. ... You may also need to affix the appropriate "doctype" and you may need to trigger the scripts to run on document load.
As an example, I tried the pasted code using the above advice on my own computer and it worked.
I'll show the complete source and then followup with a runnable version here on SO. Note that the runnable version uses SO's utility for such and as such you won't see all the various tags I mentioned, but the functionality remains the same just as with the "fiddle".
Corrected "pasted" source showing all the relevant tags you need to create:
<!doctype html> <!-- Add appropriate doctype -->
<html>
<head>
<style>
/* Paste the CSS in a style tag */
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
</style>
</head>
<body>
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>
<script>
// Paste your init scripts into the onload event to ensure they get ran after the canvas is created
window.onload = function() {
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
}
</script>
</body>
</html>
Now on to demonstrating this code works now here on SO.
Note that SO's intepreter of code also (like "fiddle") doesn't need the tags mentioned that would be needed when you copy and paste into your own editor. Therefore I re-mention where the pasted code goes in code comments.
// Your scripts will go in a <script> tag
// Use an onload event handler to ensure they get ran after the canvas is created
window.onload = function() {
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
}
/* Your CSS would go in a <style> tag */
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
<!-- Your HTML would go in the <body> tag -->
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>

Adjusting size of <canvas> to fit parent div while still maintaining draw functionality - help needed

import React, { useRef, useEffect, useState } from 'react';
import './app.css'
function App() {
const canvasRef = useRef(null)
const contextRef = useRef(null)
const divRef = useRef(null)
const [isDrawing, setIsDrawing] = useState(false)
useEffect(() => {
const canvas = canvasRef.current
canvas.width = divRef.clientWidth * 2;
canvas.height = divRef.clientHeight * 2;
canvas.style.width = `${divRef.clientWidth}px`;
canvas.style.height = `${divRef.clientHeight}px`;
const context = canvas.getContext("2d")
context.scale(2,2)
context.lineCap = "round"
//this line will provide the color - maybe change that to let users type in a color or click a color
context.strokeStyle = "black"
//here the line thickness is defined
context.lineWidth = 5
contextRef.current = context
}, [])
const startDrawing = ({nativeEvent}) => {
const {offsetX, offsetY} = nativeEvent
contextRef.current.beginPath()
contextRef.current.moveTo(offsetX, offsetY)
setIsDrawing(true)
}
const finishDrawing = () => {
contextRef.current.closePath()
setIsDrawing(false)
}
const draw = ({nativeEvent}) => {
if(!isDrawing){
return
}
const {offsetX, offsetY} = nativeEvent;
contextRef.current.lineTo(offsetX, offsetY)
contextRef.current.stroke()
}
return (
<div id="canvasDiv" ref={divRef}>
<canvas
onMouseDown={startDrawing}
onMouseUp={finishDrawing}
onMouseMove={draw}
ref={canvasRef}
/>
</div>
)
}
export default App
#canvasDiv {
width: 500px;
height: 500px;
border-style: solid;
border-width: 2px;
border-color: black;
}
#canvasDiv canvas {
width: 100%;
height: 100%;
}
Having trouble getting my draw application to work within the confines of the parent div. It does manage to resize the canvas but at the expense of the draw functionality no longer working. The code below is how it looks when it works using the entire view window as the canvas, but I am trying to implement it into a moveable window and need to be able to resize it.
const canvas = canvasRef.current
canvas.width = window.innerWidth * 2;
canvas.height = window.innerHeight * 2;
canvas.style.width = `${window.innerWidth}px`;
canvas.style.height = `${window.innerHeight}px`;

How to pan in PaperJS without using PaperScript

Referring to
How to pan using paperjs
I was trying to implement the pan.
This however only works for me when I use PaperScript and stops to work when I do it in regular JavaScript.
var canvas = document.querySelector('#myCanvas');
paper.install(window);
window.onload = function() {
paper.setup(canvas);
var myCircle = new Path.Circle(new Point(100, 70), 50);
myCircle.fillColor = 'black';
var toolPan = new paper.Tool();
toolPan.onMouseDrag = function (event) {
var offset = event.downPoint - event.point;
// console.log(offset);
paper.view.center = paper.view.center + offset;
};
view.draw();
}
html,
body {
margin: 0;
overflow: hidden;
height: 100%;
}
canvas[resize] {
width: 100%;
height: 100%;
}
<canvas id="myCanvas" resize></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.11/paper-full.min.js"></script>
Logging out offset to the console tells me it can’t substract the points. In PaperScript the exact same works well, however I have to make it work in regular JavaScript for my Project.
In PaperScript, you can use mathematical operators on Point instances but you can't do this in JavaScript so you have to use the corresponding methods instead.
point1 + point2 => point1.add(point2), etc...
Here is the corrected code:
var canvas = document.querySelector('#myCanvas');
paper.install(window);
window.onload = function() {
paper.setup(canvas);
var myCircle = new Path.Circle(new Point(100, 70), 50);
myCircle.fillColor = 'black';
var toolPan = new paper.Tool();
toolPan.onMouseDrag = function (event) {
var offset = event.downPoint.subtract(event.point);
// console.log(offset);
paper.view.center = paper.view.center.add(offset);
};
view.draw();
}
html,
body {
margin: 0;
overflow: hidden;
height: 100%;
}
canvas[resize] {
width: 100%;
height: 100%;
}
<canvas id="myCanvas" resize></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.11/paper-full.min.js"></script>

HTML attributes (width, height) of canvas change independently

I have some script on JS, it change width and height of canvas element:
function RefreshSizes (canvas) {
var temp_width = 320;
var temp_height = 240;
document.getElementById(canvas).setAttribute('width', temp_width);
document.getElementById(canvas).setAttribute('height', temp_height);
}
this functions calling right after canvas initializing.
It works fine on Chrome.
But in FireFox 49 I see that:
What could it be?
UPD#1 Tested code of BukkitmanPlays MCPE
UPD#2
Full CSS for canvas:
element {
width: 320px;
height: 240px;
}
.canvas {
border: 3px solid #E0E0E0;
z-index: 0;
position: relative;
}
html {
font: 10px/10px arial;
}
some code on one browser isn't the same on another browser, so in this case, what I would do:
function RefreshSizes (canv) {
var temp_width = 320;
var temp_height = 240;
var canvas = canv;
canvas.width = temp_width;
canvas.height = temp_height;
}
I'm sure this will work

Categories