I am SLOWLY trying to create the breakout game to get more familiar with javascript.
I am trying to re size the canvas element according to the window size, but notice the
circle I am rendering re sizes automatically according to the size of the canvas. How would i render the size of the circle independently from the size of the canvas?
//resize canvas
$(function(){
$("#canvas").width($(window).width());
});
//get a reference to the canvas
var ctx = $('#canvas')[0].getContext("2d");
//draw a circle
ctx.beginPath();
ctx.arc(75, 75, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
here is my fiddle:
http://jsfiddle.net/z25q7/3/
Thank you!
Change the canvas' width property directly, not its CSS style.width (which is what jQuery does):
$("#canvas")[0].width = $(window).width();
More information here: Size of HTML5 Canvas via CSS versus element attributes
Related
i'm receving from webserver part of image, let say 600px x 600px, which i'm drawing in canvas.
The real size of image is let say 600px x 1200px(height).
I need to create scrollbar over canvas. After i will drag scrollbar i will count, how many pixels i've moved scrollbar, send to server information and i will receive other portion of picture (600x600px) but scrolled.
The mechanism is done by me, but i need to draw scrollbar over canvas.
<b-card>
<div id="image">
<canvas
id="canvasId"
ref="canRef"
#mousedown="clickMe"
#mouseup="scrollOff"
#mousemove="scrollMe"
/>
</div>
</b-card>
How to draw scroll bar on the right side of canvas?
First, fetch the canvas element and its context
const canvas = document.getElementById('canvasId');
const ctx = canvas.getContext('2d');
Then, draw the rectangle using the stroke() function
ctx.beginPath();
ctx.rect(0, 0, 150, 100); //change to the coordinates you want
ctx.stroke();
You can control the color and the width of the line using:
ctx.lineWidth = 10;
ctx.strokeStyle = '#ff0000';
I have a page with a circular radial gradient created with CSS, that starts out at the bottom of the page and radiates upwards.
My goal is to set the meta theme color in the browser to match the colour of the gradient at the top of the page.
The problem is that the color that the gradient has at the top is dependent on the size of the view-port.
Is there any way to get the color of the top center of the page, so I can set the theme color equal to that?
My CSS gradient is defined as:
background: radial-gradient(circle at bottom center, #C25351, #EC991A 100%)
Also, here is a JS Fiddle showing my gradient: https://jsfiddle.net/61ozdy4g/
Thanks!
As far as I'm aware, there's no way to sample a gradient generated via CSS.
To achieve what you require, consider reproducing the equivalent gradient (as defined in your CSS) on a temporary <canvas> element via the Canvas Web API. Using the Canvas Web API's getImageData() method, you can then sample the pixel located at the top/center location of the canvas element to find and format the rgb() color at that point in the gradient:
// Create temporary canvas and get context for rendering
const canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
const width = document.body.clientWidth;
const height = document.body.clientWidth;
const halfWidth = Math.floor(width * 0.5);
const halfHeight = Math.floor(height * 0.5);
const gradientRange = Math.sqrt(width ** 2 + height ** 2);
// Size the canvas to match viewport
canvas.width = width;
canvas.height = height;
// Create a gradient for the fill
var grd = ctx.createRadialGradient(halfWidth, height,
0, halfWidth,
height, gradientRange);
grd.addColorStop(0, "#C25351");
grd.addColorStop(1, "#EC991A");
// Render gradient across whole fill covering canvas
ctx.fillStyle = grd;
ctx.fillRect(0, 0, width, height);
// Sample pixel at top center of canvas and format rgb string
var pixel = ctx.getImageData(halfWidth, 0, 1, 1).data;
var color = `rgb(${pixel[0]}, ${pixel[1]}, ${pixel[2]})`
alert(color)
// Add the canvas to document for visual inspection (not
// required, just included for snippet)
document.body.appendChild(canvas);
The getImageData() appears not to work in this code snippet sandbox, however you can see a working version in this jsFiddle
I'm implementing drawing on canvas with html5 and javascript.
If I dont set canvas width and height manually ( leave it default) , my drawing works good.
However, when I set canvas size either from css or javascript, my drawing looks like distorted. The line starts drawing little bit away from the line, and the line looks distorted.
Here is the code for mousedown event.
if (mouseDown)
{
previousX = currentX;
previousY = currentY;
currentX = e.clientX - canvas.offsetLeft;
currentY = e.clientY - canvas.offsetTop;
ctx.beginPath();
ctx.moveTo(previousX, previousY);
ctx.lineTo(currentX, currentY);
ctx.strokeStyle = color;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
You must set the size of canvas using its correct properties/attributes.
Canvas is an element with a bitmap. If you use CSS or style you will only scale the element, not the bitmap. The result is a blurry image.
Set correct size by doing this (and CSS is not necessary normally):
<canvas width=800 height=800></canvas>
or in JavaScript:
canvas.width = 800; // example size
canvas.height = 800;
If you use CSS, either using a rule or the style attribute in the element, to scale the canvas you will only scale a 300x150 pixel bitmap to something else which will give bad quality. Always scale the bitmap and then redraw (as the canvas will be cleared).
The canvas API is only for drawing in raster. That's why it doesn't retain clarity when it resizes. It's to be expected.
If you'd want to produce vector, you'd have to use SVG (Scalable Vector Graphics) instead. But the SVG doesn't support drawing. Producing SVG is basically through XML, so it's not flexible the same way as the canvas API is.
Here's a library that will help you accomplish drawing to the canvas in vector:
http://paperjs.org/
"Paper.js is an open source vector graphics scripting framework that runs on top of the HTML5 Canvas."
Here's another thread which enumerates more options:
HTML5 Canvas Vector Graphics?
Let's put some text on a HTML5 <canvas> with
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
ctx.font = '14px sans-serif';
ctx.fillText('Bonjour', 10, 10);
When zooming the canvas on text, one can see pixelation.
Is there a way of zooming on a canvas without having pixelation on text ?
When you fillText on the canvas, it stops being letters and starts being a letter-shaped collection of pixels. When you zoom in on it, the pixels become bigger. That's how a canvas works.
When you want the text to scale as a vector-based font and not as pixels, don't draw them on the canvas. You could create <span> HTML elements instead and place them on top of the canvas using CSS positioning. That way the rendering engine will render the fonts in a higher resolution when you zoom in and they will stay sharp. But anything you draw on the canvas will zoom accordingly.
Alternatively, you could override the browsers zoom feature and create your own zooming algorithm, but this will be some work.
When the user zooms in or out of the window, the window.onresize event handler is triggered. You can use this trigger to adjust the width and the height of the canvas css styling accordingly (not the properties of the canvas. That's the internal rendering resolution. Change the width and height attributes of the style which is the resolution it is scaled to on the website).
Now you effectively disabled the users web browser from resizing the canvas, and also have a place where you can react on the scaling input events. You can use this to adjust the context.scale of your canvas to change the size of everything you draw, including fonts.
Here is an example:
<!DOCTYPE html>
<html>
<head>
<script type="application/javascript">
"use strict"
var canvas;
var context;
function redraw() {
// clears the canvas and draws a text label
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.font = "60pt sans-serif";
context.fillText("Hello World!", 100, 100);
}
function adjustSize() {
var width = window.innerWidth;
var height = window.innerHeight;
// resize the canvas to fill the whole screen
var style = canvas.style;
style.width = width + "px";
style.height = height + "px";
// backup the old current scaling factor
context.save();
// change the scaling according to the new zoom factor
context.scale(1000 / width, 1000 / height);
// redraw the canvas
redraw();
// restore the original scaling (important because multiple calls to scale are relative to the current scale factor)
context.restore();
}
window.onload = function() {
canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
adjustSize();
}
window.onresize = adjustSize;
</script>
</head>
<body>
<canvas id ="myCanvas" width = 1000 height = 1000 ></canvas>
</body>
</html>
If you only need to scale text you can simply scale the font size.
A couple of notes on that however: fonts, or typefaces, are not just straight forward to scale meaning you will not get a smooth progress. This is because fonts are often optimized for certain sizes so the sizes in between so to speak are a result of the previous and next size. This can make the font look like it's moving around a little when scaled up and is normal and expected.
The approach here uses a simply size scale. If you need an absolute smooth scale for animation purposes you will have to use a very different technique.
The simple way is:
ctx.font = (fontSize * scale).toFixed(0) + 'px sans-serif';
An online demo here.
For animation purposes you would need to do the following:
Render a bigger size to an off-screen canvas which is then used to draw the different sizes
When the difference is too big and you get problems with interpolation you will have to render several of these cached text images at key sizes so you can switch between them when scaling factor exceeds a certain threshold.
In this demo you can see that at small sizes the pixels gets a bit "clumpy" but otherwise is much smoother than a pure text approach.
This is because the browser uses bi-linear interpolation rather than bi-cubic with canvas (this may or may not change in the future) so it's not able to interpolate properly when the difference gets to big (see below for solution with this issue).
The opposite happens at big sizes as the text gets blurry also due to interpolation.
This is where we would have to switch to a smaller (or bigger) cached version which we then scale within a certain range before we again switch.
The demo is simplified to show only a single cached version. You can see halfway through that this works fine. The principle would be in a full solution (sizes being just examples):
(Update Here is a demo of a switched image during scale).
-- Cached image (100px)
-- Draw cached image above scaled based on zoom between 51-100 pixels
-- Cached image (50px) generated from 100px version / 2
-- Draw cached image above scaled based on zoom between 26-50 pixels
-- Cached image (25px) generated from 50px version / 2
-- Draw cached image above scaled based on zoom between 1-25 pixels
Then use a "sweet spot" (which you find by experiment a little) to toggle between the cached versions before drawing them to screen.
var ctx = canvas.getContext('2d'),
scale = 1, /// initial scale
initialFactor = 6, /// fixed reduction scale of cached image
sweetSpot = 1, /// threshold to switch the cached images
/// create two off-screen canvases
ocanvas = document.createElement('canvas'),
octx = ocanvas.getContext('2d'),
ocanvas2 = document.createElement('canvas'),
octx2 = ocanvas2.getContext('2d');
ocanvas.width = 800;
ocanvas.height = 150;
ocanvas2.width = 400; /// 50% here, but maybe 75% in your case
ocanvas2.height = 75; /// experiment to find ideal size..
/// draw a big version of text to first off-screen canvas
octx.textBaseline = 'top';
octx.font = '140px sans-serif';
octx.fillText('Cached text on canvas', 10, 10);
/// draw a reduced version of that to second (50%)
octx2.drawImage(ocanvas, 0, 0, 400, 75);
Now we only need to check the sweet spot value to find out when to switch between these versions:
function draw() {
/// calc dimensions
var w = ocanvas.width / initialFactor * scale,
h = ocanvas.height / initialFactor * scale;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (scale >= sweetSpot) {
ctx.drawImage(ocanvas, 10, 10, w, h); /// use cached image 1
} else {
ctx.drawImage(ocanvas2, 10, 10, w, h); /// use cached image 2
}
}
So why not just draw the second cached image with a font? You can do that but then you are back to the issue with fonts being optimized for certain sizes and it would generate a small jump when scaling. If you can live with that then use this as it will provide a little better quality (specially at small sizes). If you need smooth animation you will have to reduce a larger cached version in order to keep the size 100% proportional.
You can see this answer on how to get a large image resized without interpolation problems.
Hope this helps.
Hey Everyone I am new to html5 canvas as I would like to know is there any possibility of getting the image height,width and angle values while resizing and rotating.The image which displays what i want.
I want that process after dropping in to canvas as i searched Google for this couldn't find relevant answer almost everyone is showing the positions of image in canvas that is to kept in code but i want the image should should display its values automatically by click on dimensions button.Thanks in advance any help would be great.
The image should display its dimensions in canvas according to image like if image is changed(or re-sized or rotate automatically the dimensions should change using button click function).
You can play with canvas in the following manner
<canvas id="myCanvas">Your browser does not support the canvas tag.</canvas>
<script type="text/javascript">
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// Draw blue rectangle
ctx.fillStyle = '#0065BD';
ctx.fillRect(0, 0, 125, 75);
// Draw white X
ctx.beginPath();
ctx.lineWidth = "15";
ctx.strokeStyle = "white";
ctx.moveTo(0, 0);
ctx.lineTo(125, 75);
ctx.moveTo(125, 0);
ctx.lineTo(0, 75);
ctx.stroke();
</script>
Hope this helps you.