I have a function that draw a CANVAS line and make this get the same coordinates of a <div> by using offsetLeft and move its searching the same position of the <div>. It is working good.
drawCanvas() {
const c = document.getElementById("canvas");
const lineH = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
const positionCanvas = () => {
const divPosition = document.querySelector('.myDiv').offsetLeft
lineV.fillStyle = "grey";
lineV.fillRect(divPosition , 0, 2, window.innerHeight);
lineV.fill();
}
positionCanvas()
window.onresize = () => {
lineV.height = window.innerHeight;
positionCanvas()
}
The problem is I don't know how avoid the default CANVAS behavior that duplicates many times the line when I resize the windows. How do I solve it? Thank you
The answer is:
const positionCanvas = () => {
lineV.clearRect(0, 0, c.width, c.height); //<-- new line added in the code
//... rest of the code ommited
Related
I am trying to record audio and draw the bars on canvas. But I am stuck on resizing the canvas according to the length of bars that are there. Following is the JS for all the work that is being done. I tried adding function to resize canvas, and override the canvas width but none is working.
css width:auto; is also not working. Following is the function That I have used to resize canvas according the to BARS length that are drawn.
I tried to override the canvas width inside stop function [Current Visual of Bars inside canvas][1]
Following code can be tested in this codepen https://codepen.io/smashingmag/pen/qBVzRaj
function resizeCanvas() {
CANVAS.width = BARS.length;
console.log(CANVAS.width);
}
resizeCanvas();
//Getting and initializing canvas from html to create bars
const CANVAS = document.querySelector('canvas')
const DRAWING_CONTEXT = CANVAS.getContext('2d')
//setting canvas height and width and bars configuration
CANVAS.width = CANVAS.offsetWidth
CANVAS.height = CANVAS.offsetHeight
const CONFIG = {
fft: 2048,
show: true,
duration: 0.8,
fps: 100,
barWidth: 0.1,
barMinHeight: 0.01,
barMaxHeight: 0.3,
barGap: 0.01,
}
//here I am creating bars
const addBar = (volume = 100) => {
const BAR = {
x: CANVAS.width + CONFIG.barWidth / 2,
// Note the volume is 0
size: gsap.utils.mapRange(
50,
150,
CANVAS.height * CONFIG.barMinHeight/3,
CANVAS.height * CONFIG.barMaxHeight*3
)(volume),
}
const drawBars = () => {
DRAWING_CONTEXT.clearRect(0, 0, CANVAS.width, CANVAS.height)
for (const BAR of BARS) {
drawBar(BAR)
}
}
STOP.addEventListener('click', () => {
if (recorder) recorder.stop()
AUDIO.setAttribute('controls', true)
AUDIO_CONTEXT.close()
timeline.pause()
SCRUB(START_POINT)
var delayInMilliseconds = 1000; //1 second
setTimeout(function() {
//Here i am getting the canvas image on console
const img = CANVAS.toDataURL("image/png");
console.log(img);
}, delayInMilliseconds);
})
drawBars()
[1]: https://i.stack.imgur.com/JBBjT.png
I looked at your codepen and I think yours has a simple solution
function resizeCanvas() {
CANVAS.style.width = BARS.length + "px";
CANVAS.width = BARS.length;
}
This is just setting the CSS width property using javascript.
Doing CANVAS.width = 500 does not overwrite the CSS which tells it to be 300px. So it was still a CSS problem.
I'm trying to render canvas and draw rectangle on it using svelte.js, but it does not work if I write rendering code on the component side.
Here is the reproduction REPL.
It works if I move entire code in Canvas.svelte to app.svelte.
App.svelte:
<script>
import Canvas from './Canvas.svelte';
</script>
<Canvas/>
Canvas.svelte:
<script>
import { onMount } from 'svelte';
let canvasEl;
const canvas = {
width: 1000,
height: 1000
};
const drawRect = (context) => {
context.beginPath();
context.fillStyle = '#000000';
context.rect(0, 0, 40, 10);
context.fill();
};
onMount(() => {
console.log('Onmount');
const context = canvasEl.getContext('2d');
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
drawRect(context);
});
</script>
<canvas bind:this={canvasEl} width={canvas.width} height={canvas.height} />
Does anyone know the solution?
Thank you,
Didn't find a reason of error, but found the source:
onMount(() => {
//...
// this 2 lines cause silent error
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
//...
});
Remove them and you will see the canvas and rect
I can really use some help, my goal is to add few lines to the canvas in different places, it means to use the function drawText few times, for some reason if I don't use drawText inside the onload of drawImage the text does not rendering I am really stuck and can use some help, my main target it to make website that can edit pictures and make memes (e.g.: https://imgflip.com/memegenerator)and adding text line is what i am getting stuck on because I don't understand how to render new text line while save the old one, every time i start new line its like the image rendering all over again and start from the beginning.
// Function to load image on the canvas
function drawImg(url) {
gCurrLineIdx = getCurrLineIdx();
let currLine = gMeme.lines[gCurrLineIdx];
const img = new Image();
img.src = url;
img.onload = () => {
gCtx.drawImage(img, 0, 0, gElCanvas.width, gElCanvas.height);
//If you dont call drawText the text does not render to the canvas
drawText(currLine.txt, currLine.size, currLine.fontColor, currLine.strokeColor, currLine.align, currLine.font, gElCanvas.width / 2, currLine.y);
};
}
// Function to add text on the canvas
function drawText(text = '', fontSize = 20, fontColor = 'white', strokeColor = 'black', align = 'center', font = "ariel", x = gElCanvas.width / 2, y = 20) {
gCtx.strokeStyle = strokeColor;
gCtx.fillStyle = fontColor;
gCtx.font = `${fontSize}px ${font}`;
gCtx.textAlign = align;
gCtx.fillText(text, x, y);
gCtx.strokeText(text, x, y);
}
//Function to add new text line on the canvas.
function onAddTextLine() {
let textInput = document.getElementById('text-input');
textInput.value = '';
addTextLine();
gCurrLineIdx = getCurrLineIdx();
var currLine = gMeme.lines[gCurrLineIdx];
drawText(currLine.txt, currLine.size, currLine.fontColor, currLine.strokeColor, currLine.align, currLine.font, gElCanvas.width / 2, currLine.y);
}
The question I see here is:
how to render new text line while save the old one
Looks like in your code you are drawing things independently, below is a different approach the class Meme has a few functions to add text and image but every time anything change the entire canvas is cleared (clearRect) and every element is re-drawn, the magic is in the this.draw(), that is the call to the common function that does all the drawing.
To keep my sample small I hard-coded many of the things you had as parameters, it should be easy for you to reintroduce them if you need
class Meme {
constructor(ctx, width, height) {
this.ctx = ctx;
this.ctx.font = '80px Arial';
this.ctx.fillStyle = "blue"
this.ctx.textAlign = "center"
this.width = width;
this.height = height;
}
addHeadText(text) {
this.htext = text;
this.draw();
}
addFootText(text) {
this.ftext = text;
this.draw();
}
addImage(image_src) {
this.image = new Image();
this.image.src = image_src;
this.image.onload = () => {
this.draw()
};
}
draw() {
this.ctx.beginPath();
this.ctx.clearRect(0, 0, this.width, this.height)
if (this.image) {
this.ctx.drawImage(this.image, 0, 0, this.width, this.height);
}
if (this.htext) {
this.ctx.textBaseline = "top";
this.ctx.fillText(this.htext, this.width / 2, 0);
}
if (this.ftext) {
this.ctx.textBaseline = "bottom";
this.ctx.fillText(this.ftext, this.width / 2, this.height);
}
this.ctx.closePath();
}
}
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
meme = new Meme(ctx, canvas.width, canvas.height)
meme.addHeadText("Hello");
meme.addFootText("World");
meme.addImage("http://i.stack.imgur.com/UFBxY.png");
document.getElementById('htext').onkeyup = (event) => {
meme.addHeadText(event.srcElement.value);
};
document.getElementById('ftext').onkeyup = (event) => {
meme.addFootText(event.srcElement.value);
};
Head Text:<input type="text" id="htext" name="ftext" style="width: 140px;" value="Hello"><br>
Foot Text:<input type="text" id="ftext" name="ftext" style="width: 140px;" value="World"><br>
<canvas id="c" width=280 height=380 style="border:2px solid red;"></canvas>
I have an image on canvas or a set of images that i draw on the canvas. I can draw them fine but I want to change the window level of the image on canvas by dragging the mouse over it. I've seen a lot of external javascript api's but they're quite huge and i don't want to use them for this purpose.
here's my JSFIDDLE that is basically drawing an image on the canvas
this is how my code looks
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
// Specify the src to load the image
img.src = "http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample5_l.jpg";
i need something with basic JS or JQuery. it would be great if you can point me in the right direction using a sample code.
Thanks in advance.
If you want to use JavaScript, try something like:
<script>
var c = document.getElementById("drawingboard");
var ctx = c.getContext("2d");
var mouseDown = 0;
document.body.ontouchstart = function() {
mouseDown+=1;
}
document.body.ontouchend = function() {
mouseDown-=1;
}
function draw(event){
ctx.color='gold';
ctx.fillStyle = "lime";
ctx.drawImage(img,event.clientX,event.clientY);}
</script>
This is what I gained after some research:
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const rangeMin = level - window / 2;
const rangeMax = level + window / 2;
const totalSize = canvas.width * canvas.height;
for (let idx = 0; idx < totalSize; idx++) {
if (imageData.data[idx] < rangeMin) {
imageData.data[idx] = 0;
} else if (imageData.data[idx] > rangeMax) {
imageData.data[idx] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
I've created an ember component with a rectangular block inside a green canvas.
What I'm having trouble with is adding a keyboard-input command for A S D W to move the rectangle around the canvas. It's easy enough to do in regular javascript or jquery but inside the component model I'm a bit lost. Any help regarding the function would be very useful.
Linked here is an ember javascript bin: http://emberjs.jsbin.com/miyatoti/1/edit
Here is my present code of the component.
App.BoxGameComponent = Em.Component.extend({
tagName:'canvas',
width: 325,
height: 280,
refresh:30,
attributeBindings:['width', 'height'],
stars:null,
on:false,
build: function(){
var canvas = this.$()[0],
ctx = canvas.getContext('2d'),
shippos = [150, 120],
height = this.get('height'),
width = this.get('width');
this.set('shippos', shippos);
this.set('ctx', ctx);
this.set('on', true);
}.on('didInsertElement'),
kill: function(){
this.set('on', false);
}.on('willDestroyElement'),
clear: function () {
var ctx = this.get('ctx'),
height = this.get('height'),
width = this.get('width');
ctx.fillStyle = 'green';
ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.rect(0, 0, width, height);
ctx.closePath();
ctx.fill();
},
box: function () {
var that = this;
var ctx = this.get('ctx'),
height = this.get('height'),
width = this.get('width'),
shippos = this.get('shippos');
var posx = shippos[0],
posy = shippos[1];
ctx.rect(posx,posy,50,50);
ctx.stroke();
},
game: function(){
if(this.get('on')){
this.loop();
}
}.observes('on'),
loop: function () {
var refreshRate = this.get('refresh');
this.clear();
this.box();
if(this.get('on')){
Em.run.later(this, this.loop, refreshRate);
}
}
});
If anyone can help I've been slamming my brain at this for hours.
Hooking up keyup a canvas element is a bit trickier since the canvas doesn't get focus. So you just hook up to the window (and then destroy it later).
$(window).on('keyup', {self:this}, this.handleKeyUp );
http://emberjs.jsbin.com/miyatoti/2/edit