I programmatically create several svg-images by JavaScript. Images are lines.
function create(elem) { //function for create svg elem
var svg = "http://www.w3.org/2000/svg";
return document.createElementNS(svg, elem);
function set(elem, atrArr) { //function for set attributes svg elem
for (var i in atrArr) {
elem.setAttribute(i, atrArr[i])
}
}
function someFunc(valueWidth, valueHeight) {
var SVG = create('svg'); //canvas
var line = create('line'); //line
var width = valueWidth; //some value
var heigth = valueHeight; //some value
set(SVG, { //set canvas
version: '1.1',
width: width,
height: height
});
//set line
set(line, { x1: 0, x2: width, y1: 0, y2: height, style: 'stroke:rgb(0,0,0);stroke-width:1' });
SVG.style.position = 'absolute';
SVG.appendChild(line);
}
If height or width < 0.5, then line is drawn only in IE.
Can I draw line in other browsers without changing the size of the canvas?
This worked fine for me in Chrome, after correcting the syntax errors (height vs heigth), and appending the svg element to the body:
var SVG = create('svg'); //canvas
document.body.appendChild(SVG);
http://jsfiddle.net/4jRZT/5/
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 am using fabric js v4.1.0 and I would like to show the blue select boundary of the selected object outside the canvas boundary if it is partially dragged out of canvas and have the scaling and rotate functions also in this as the object which is selected inside the canvas.
Here is a demo of my current code https://codepen.io/raja-basumatary/pen/qBZGobQ
function isCanvasSupported() {
var elem = document.createElement("canvas");
return !!(elem.getContext && elem.getContext("2d"));
}
if (!isCanvasSupported()) {
document.getElementById("nocanvas").className = "";
document.getElementById("myCanvas").className = "hidden";
} else {
// Constants
var canvasHeight = 580;
var canvasWidth = 865;
var canvas = new fabric.Canvas("myCanvas");
canvas.setHeight(canvasHeight);
canvas.setWidth(canvasWidth);
var rect = new fabric.Rect({
left: 150,
top: 100,
fill: "#eef",
width: 150,
height: 250
});
canvas.add(rect);
}
I want something like this
image
I am using PDF.js to show PDF in browser. PDF.js uses canvas to render PDF. I have js scripts that draws the lines on the canvas when user double clicks on the canvas. It also adds X check mark to remove the already drawn line.
based on my research i cannot simply just remove the line from the canvas because underneath pixels are gone when you draw something on it. To get it working i have to store lines and then clear canvas and re-load canvas and re-draw lines
Issue
I am not able to store canvas and restore canvas. When i click on X i was able to get lines re-drawn but canvas does not get restored. Canvas remains blank
Run the demo in full page
$(function () {
var $canvas = $("#myCanvas");
var canvasEl = $canvas.get(0);
var ctx = canvasEl.getContext("2d");
var lines = [];
var backupCanvas = document.createElement("canvas");
var loadingTask = pdfjsLib.getDocument('https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf');
loadingTask.promise.then(function (doc) {
console.log("This file has " + doc._pdfInfo.numPages + " pages");
doc.getPage(1).then(page => {
var scale = 1;
var viewPort = page.getViewport(scale);
canvasEl.width = viewPort.width;
canvasEl.height = viewPort.height;
canvasEl.style.width = "100%";
canvasEl.style.height = "100%";
var wrapper = document.getElementById("wrapperDiv");
wrapper.style.width = Math.floor(viewPort.width / scale) + 'px';
wrapper.style.height = Math.floor(viewPort.height / scale) + 'px';
page.render({
canvasContext: ctx,
viewport: viewPort
});
storeCanvas();
});
});
function storeCanvas() {
backupCanvas.width = canvasEl.width;
backupCanvas.height = canvasEl.height;
backupCanvas.ctx = backupCanvas.getContext("2d");
backupCanvas.ctx.drawImage(canvasEl, 0, 0);
}
function restoreCanvas() {
ctx.drawImage(backupCanvas, 0, 0);
}
$canvas.dblclick(function (e) {
var mousePos = getMousePos(canvasEl, e);
var line = { startX: 0, startY: mousePos.Y, endX: canvasEl.width, endY: mousePos.Y, pageY: e.pageY };
lines.push(line);
drawLine(line, lines.length - 1);
});
function drawLine(line, index) {
// draw line
ctx.beginPath();
ctx.strokeStyle = '#df4b26';
ctx.moveTo(line.startX, line.startY);
ctx.lineTo(line.endX, line.endY);
ctx.closePath();
ctx.stroke();
// add remove mark
var top = line.pageY;
var left = canvasEl.width + 20;
var $a = $("<a href='#' class='w-remove-line'>")
.data("line-index", index)
.attr("style", "line-height:0")
.css({ top: top, left: left, position: 'absolute' })
.html("x")
.click(function () {
var index = $(this).data("line-index");
$(".w-remove-line").remove();
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
// restore canvas
restoreCanvas();
lines.splice(index, 1);
for (var i = 0; i < lines.length; i++) {
drawLine(lines[i], i);
}
});
$("body").append($a);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
X: Math.floor(evt.clientX - rect.left),
Y: Math.floor(evt.clientY - rect.top),
};
}
});
canvas {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.228/pdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<b> Double Click on PDF to draw line and then click on X to remove lines</b>
<div id="wrapperDiv">
<canvas id="myCanvas"></canvas>
</div>
The PDF.js render() function is async so you need to store the canvas after the render has finished. Your code is firing storeCanvas() too early and storing a blank canvas. Easy fix, render() returns a promise so ...
page.render({
canvasContext: ctx,
viewport: viewPort
}).then( () => {
storeCanvas();
});
https://jsfiddle.net/fyLant01/1/
Reference: from https://github.com/mozilla/pdf.js/blob/master/src/display/api.js#L998
/**
* Begins the process of rendering a page to the desired context.
* #param {RenderParameters} params Page render parameters.
* #return {RenderTask} An object that contains the promise, which
* is resolved when the page finishes rendering.
*/
I have created a rectangle on HTML canvas. I want to have a 45 degree rotation animation on this rectangle using Anime.js. I have seen number of posts on rectangle rotation but can't figure out how to rotate it using Anime.js. Following is my <body> tag:
<body class="container">
<canvas></canvas>
<script src="anime.min.js" type="text/javascript"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var canvas = document.querySelector('canvas');
canvas.width = 1280;
canvas.height = 720;
var c = canvas.getContext('2d');
//Create box
function Box(size) {
var box = {};
box.size = size;
box.x = 640 - (box.size/2);
box.y = 250 - (box.size/2);
box.translateX = 0;
box.translateY = 0;
box.degree = 0;
box.color = "#ffffff";
box.draw = function () {
c.save();
c.fillStyle = box.color;
c.translate(box.translateX, box.translateY);
c.rotate(box.degree * Math.PI/180);
c.fillRect(box.x, box.y, box.size, box.size);
c.restore();
};
return box;
}
var box = new Box(300);
box.draw();
anime.timeline().add({
targets: box,
x: -100,
y: -125,
translateX: 640,
translateY: 250,
degree: 45,
duration: 1000
})
});
</script>
</body>
Can anyone please help?
You mix up two different topics. Anime.js is good to animate dom elements. So in your case you can animate only complete canvas. Is not possible to animate rectangle inside. This is because animate.js is using DOM selectors and CSS technique.
So to animate complete canvas you can assign id
canvas id="myCanvas"></canvas>
In java-script code change only target
anime.timeline().add({
targets: '#myCanvas',
Other way is to paint rotated rectangle by your own on canvas.
Attempting to inject SVG elements with raw javascript. I can inspect and see the elements have been loaded, but dimensions end up being 0x0 instead of the size set on the element.
(function() {
// Constructor
this.Loading = function() {
this.svgNamespace = "http://www.w3.org/2000/svg";
var svg = createSvgObject("svg", "loaderSvg");
svg.setAttributeNS(null, "width", 200);
svg.setAttributeNS(null, "height", 200);
document.getElementById("possibleLoadingLocation").appendChild(svg);
var circle = createSvgObject("circle", "test");
circle.setAttribute("cx", 40);
circle.setAttribute("cy", 40);
circle.setAttribute("r", 30);
circle.setAttribute("stroke", "#000");
circle.setAttribute("stroke-width", 2);
circle.setAttribute("fill", "#f00");
svg.appendChild(circle);
}
function createSvgObject(elementType, elementId) {
if (elementType === undefined || elementType == null) {
throw "elementType is required to createSvgObject";
}
var element = document.createElementNS(this.svgNamespace, elementType);
if (elementId != null) {
element.setAttributeNS(null, "id", elementId);
}
return element
}
}());
var myLoading = new Loading();
Both the SVG object and the Circle object arrive with dimensions of 0x0. I have used css in the below example to force the svg to match the dimensions of the div containing it. I have also copied the exact svg code from the inspection into the body without css where I can see it sizing properly.
Thanks for any help.
https://jsfiddle.net/t92m5L8s/3/
Change the location of
this.svgNamespace = "http://www.w3.org/2000/svg";
to before:
this.Loading = function() {