How To wipe the last canvas paint in qml - javascript

Canvas {
id: canvas
onPaint: {
if (personalInfo.count === 0) {
return
}
var ctx = canvas.getContext("2d");
ctx.globalCompositeOperation = "source-over";
var points = []
for (var i = 0; i < personalInfoModel.dataCount(); i++) {
var temp = personalInfoModel.get(i)
points.push({
date: temp.date,
heartRate: temp.heartRate,
temprature: temp.temprature,
pressure: temp.bloodPressure
}
)
}
drawAxis(ctx)
drawGridLineAndUnitNum(ctx, chart.activeChart, points, "x", 15);
}
}
I have two button. If button A is clicked, then set chart.activeChart to 7 and call cavas.requestPaint() on A::onClicked, on cavas.drawGridLineAndUnitNum draw seven vertical line. If button B is clicked besides set chart.activeChart to 30, all same to A::onClicked. I hope that when A is clicked, canvas wipe the drawn line which product by B is clicked and vice versa. But in fact, it always reserve the line draw by last time.

A Context2D, associated to a specific Canvas, provides two useful functions:
fillRect
clearRect
In most cases, it could be possible to "clear" a Canvassimply by filling it with the background color, i.e. by using fillRect. That's the approach of the StocQt example, which has a white background.
However, if the background is transparent, filling it does not remove other strokes and thus does not make much sense. In this case, the only possible way to clear the Canvas is by removing all the strokes, i.e. by using clearRect.
I use a transparent background and thus clearRect is the way to go for me.

Related

Why do HTML canvas outline colors appear lighter? [duplicate]

This question already has an answer here:
html 5 canvas LineTo() line color issues
(1 answer)
Closed 6 months ago.
On what are seemingly random occasions, the color of HTML canvas elements appear lighter than they are actually supposed to be. In the code snippet below, I set both the outline and fill to "red", which is supposed to be a valid CSS color corresponding to #ff0000, but under close inspection, the color of the outline is #ff8080. Why does this happen?
In addition, while the reproducible example was only on a outline, I initially saw this happen when I tried to create a black rectangle (#000) and it was gray. (#808080)
Is there a canvas context setting for this? Perhaps a rendering error?
render()
function render() {
var canvas = document.createElement("canvas")
canvas.width = 100
canvas.height = 100
console.log("created canvas",canvas)
// CREATE CONTEXT
var context = canvas.getContext("2d")
console.log("created context",context)
context.strokeStyle = "red"
context.strokeRect(10,10,50,50)
context.fillStyle = "red"
context.fillRect(12.5,12.5,45,45)
document.body.appendChild(canvas)
}
The Problem is Anti-Aliasing. The line is drawn between two pixels and therefor only half as bright on each of them. If you want a crisp edge, you need to draw it at 0.5 pixel offsets, see below. With rects it is exactly the opposite. I don't know how portable it is, so you might need to experiment.
render()
function render() {
var canvas = document.createElement("canvas")
canvas.width = 100
canvas.height = 100
console.log("created canvas",canvas)
// CREATE CONTEXT
var context = canvas.getContext("2d")
console.log("created context",context)
context.strokeStyle = "red"
context.strokeRect(10.5,10.5,50,50)
context.fillStyle = "red"
context.fillRect(12,12,45,45)
document.body.appendChild(canvas)
}
<html>
<body>
</body>
</html>

Fabric.js Canvas - Make one type of object always stay below the other

I am working on a project in which I have to add rectangles and add triangles into those rectangles. I get the currently selected rectangle using this
const rect = canvas.getActiveObject().aCoords
Then I check if the mouse click is in the rectangle and if true I add a triangle.
const x = event.pointer.x
const y = event.pointer.y
if (rect.tl.x + 20 < x < rect.br.x - 20 && rect.tl.y + 20 < y < rect.br.y - 20) {
var points = regularPolygonPoints(3, 10);
var myPoly = new fabric.Polygon(points, {
stroke: 'red',
left: x,
top: y,
strokeWidth: 2,
strokeLineJoin: 'bevil'
}, false);
canvas.add(myPoly);
}
The problem is the whenever the rectangle is selected it comes on top of all the added triangles and only after I click away to deselect the rectangle, the triangles appear from beneath.
Please see the images below to better understand
Unselected
Selected rectangle coming on top of the triangles
What I want is that even if the rectangle is selected it always stays below the triangles.
http://fabricjs.com/docs/fabric.Canvas.html#preserveObjectStacking
Indicates whether objects should remain in current stack position when selected. When false objects are brought to top and rendered as part of the selection group
Set your canvas.preserveObjectStacking to true (it's false by default).
It will prevent the selection from bringing objects to the front, but keep in mind that this will rely on the order in which you've added your objects.

Fading trailing stroke in p5.js

How to effectively create curveVertex with an array of p5.Vector points which fades (decreases opacity) the trail after the mouse position?
So far the following code removes the trailing points after a certain amount of time, creating the effect of trailing after the mouse, but it does not create a translucent trail. The trailing stroke just goes away.
const trail = sk => {
let points = [];
let fadeTime = 1000;
sk.setup = () => {
sk.createCanvas(300, 600);
sk.noFill();
};
sk.draw = () => {
sk.clear();
sk.beginShape();
for (let i = points.length - 1; i >= 0; i--) {
let p = points[i];
let timeAlive = sk.millis() - p.z;
if (timeAlive > fadeTime) {
// start removing last point
points.shift();
} else {
sk.strokeWeight(10);
sk.strokeJoin(sk.ROUND);
sk.strokeCap(sk.ROUND);
sk.stroke(255, 255, 255);
sk.curveVertex(p.x, p.y);
}
}
sk.endShape();
}
// Add more points forward when dragging mouse
sk.touchMoved = () => {
points.push(sk.createVector(sk.mouseX, sk.mouseY, sk.millis()));
return false;
}
};
let mySketch = new p5(trail, elementId);
The problem is that shapes created using the beginShape() and vertex functions (including curveVertex()) can only have a single stroke and fill color. So you can't color parts of the shape differently from the rest of the shape.
To prove this, try changing this line:
sk.stroke(255, 255, 255);
To this line:
sk.stroke(random(256));
To get around this, you could make each section of your curve its own shape with its own color. Start by just making each section a random color.
Then you need to base the color of each section off of the current index. I recommend drawing out a few examples. If a curve has 10 sections, what color should section 1 have? Section 2? Section 10? Repeat that process until you notice a pattern.
If you get stuck, please post an updated MCVE in a new question, and we'll go from there. Good luck.

How could I make an optimized canvas pixel rendering?

I'm researching for a method for drawing a pixel with a well optimised method,
reducing the probability of fps drops. I use 2d, because it's more easy than webgl contexts. Here is a code that I tried:
<script>
document.write(".")
document.body.innerHTML=""
document.body.style.margin="0 0 0 0"
c=document.createElement("canvas")
document.body.appendChild(c)
ctx=c.getContext("2d")
setInterval(function(){
c.width=innerWidth
c.height=innerHeight
for(x=0;x<innerWidth;x++){
for(y=0;y<innerHeight;y++){
ctx.fillStyle="rgba(0,0,0,1)"
ctx.fillRect(x,y,x+1,y+1)
}}},1)
</script>
But when I save this as html file and open the html file with a navigator, the navigator gets caught and takes more than 2 seconds for load an image.
(() => {
document.write(".")
document.body.innerHTML=""
document.body.style.margin="0 0 0 0"
c=document.createElement("canvas")
document.body.appendChild(c)
ctx=c.getContext("2d")
c.width=innerWidth
c.height=innerHeight
x = 0;
y = 0;
function drawPixel() {
ctx.fillStyle="rgba(0,0,0,1)";
ctx.fillRect(x,y,x+1,y+1);
x ++;
if (x > innerWidth) {
x = 0;
y ++;
}
if (y < innerHeight)
requestAnimationFrame(drawPixel);
}
requestAnimationFrame(drawPixel)
})()
Try this, it's almost the same you did. You need to change some parts to get a better perfomance, i just adapted your code to work with requestAnimationFrame.
The quickest way to draw pixels one at a time is to create a image data object and add a typed array that holds each pixel as a 32 bit integer.
// assuming the ctx has been defined
var pixelData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
pixelData.data32 = new Uint32Array(pixelData.data.buffer); // create 32bit pixel
The quickest way to fill the buffered pixel data is via the typedArray.fill function
const white = 0xFFFFFFFF;
pixelData.data32.fill(white);
Or green
const green = 0xFF00FF00;
pixelData.data32.fill(green);
To set on pixel via its coordinates
function setPixel(x,y,color){
pixelData.data32[x + y * ctx.canvas.width] = color;
}
setPixel(10,10,0xFFFFFFFF);
To move the pixels to the canvas use
ctx.putImageData(pixelData,0,0);
The colour channels for a 32bit pixels are in the order ABGR such that 0xFF000000 is black 0x00000000 is transparent, 0xFFFF0000 is blue, 0xFF00FF00 is green and 0xFF0000FF is red. (note in some very rare situations the can change depending on the hardware's Endianness )

HTML canvas double buffering frame-rate issues

I have a full-screen canvas with 3 images drawn on it. When I resize the window, these images change position; however, it appears to be very glitchy, more so in Firefox.
I've been reading that double-buffering should resolve this issue, but I'm wondering how I would double buffer when the next position is unknown. That is to say, I cannot determine what should be buffered in the future, so how would this be possible?
Here is one source that seems doable, but I do not fully understand the concept Fedor is trying to explain.
Does HTML5/Canvas Support Double Buffering?
So far I have,
$canvas = $('#myclouds')[0];
$canvas_buffer = $('canvas')[0].insertAfter($canvas).css('visibility', 'hidden');
context = $canvas.getContext('2d');
context_buffer = $canvas_buffer.getContext('2d');
clouds_arr = [$canvas, $canvas_buffer];
$(window).resize(function () {
drawCanvas();
};
function initCanvas() {
// Sources for cloud images
var cloud1 = '/js/application/home/images/cloud1.png',
cloud2 = '/js/application/home/images/cloud2.png',
cloud3 = '/js/application/home/images/cloud3.png';
// add clouds to be drawn
// parameters are as follows:
// image source, x, y, ratio, adjustment)
addCloud(cloud1, null, 125, .03);
addCloud(cloud2, null, 75, .15);
addCloud(cloud3, null, 50, .55);
addCloud(cloud1, null, 125, .97, 300);
addCloud(cloud2, null, 70, .85, 300);
addCloud(cloud3, null, 45, .5, 300);
// Draw the canvas
drawCanvas();
}
function drawCanvas() {
// Reset
$canvas.attr('height', $window.height()).attr('width', $window.width());
// draw the clouds
var l = clouds.length;
for (var i = 0; i < l; i++) {
clouds[i].x = ($window.width() * clouds[i].ratio) - clouds[i].offset;
drawimage(context, clouds[i]);
}
}
function Cloud() {
this.x = 0;
this.y = 0;
}
function addCloud(path, x, y, ratio, offset) {
var c = new Cloud;
c.x = x;
c.y = y;
c.path = path;
c.ratio = ratio || 0;
c.offset = offset || 0;
clouds.push(c);
}
function drawimage(ctx, image) {
var clouds_obj = new Image();
clouds_obj.src = image.path;
clouds_obj.onload = function() {
ctx.drawImage(clouds_obj, image.x, image.y);
};
}
I think maybe you are misunderstanding what double buffering is. Its a technique for smooth real-time rendering of graphics on a display.
The concept is you have two buffers. Only one is visible at any one time. When you go to draw the elements that make up a frame you draw them to the invisible buffer. In you case the clouds. Then you flip the buffers making the hidden one visible and the visible one hidden. Then on the next frame you draw to the now newly hidden buffer. Then at the end of drawing you flip back.
What this does is stop the user seeing partial rendering of elements before a frame is complete. On gaming systems this would also be synced up with the vertical refresh of the display to be really smooth and stop artefacts such as tearing to occur.
Looking at you code above you seem to have created the two canvas elements, but you're only using the first Context object. I assume this is incomplete as no flipping is taking place.
Its also worth noting that the window resize event can fire continuously when dragging which can cause frantic rendering. I usually create a timer on the resize event to actually re-render. This way the re-render only happens once the user stops resizing for a few milliseconds.
Also, your draw routine is creating new Image objects every time which you don't need to do. You can use one image object and render to the canvas multiple times. This will speed up your render considerably.
Hope this helps.

Categories

Resources