Rotate multiple images in Javascript - angularjs

I have background image on background of canvas. And i want to put another image on background image. SO i can rotate upward image in any direction. I am trying javascript code which is available on internet. But both images were rotated. I want to rotate only upward image with some angle.
/* Upload first image to 0,0 co-ordinate. */
ctx.beginPath();
var imageObj = new Image();
imageObj.onload = function()
{
ctx.drawImage(imageObj, 0, 0, 300, 150);
};
imageObj.src = 'C://Users//rajesh.r//Downloads//images//images.jpg';
options.ctx.fill();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ctx.beginPath();
ctx.translate(400,300);
ctx.rotate(2*Math.PI / 8);
var thumbImageObj = new Image();
thumbImageObj.onload = function()
{
ctx.drawImage(thumbImageObj, 0, 0, 120, 20);
};
thumbImageObj.src = 'C://Users//rajesh.r//Downloads//images//images.png';
ctx.fill();
I want some solution so i can rotate second image by some angle.

When you call rotate on your canvas, you're not rotating an individual image, but instead rotating the entire canvas. To only rotate the second image you need take advantage of the save and restore methods provided by the canvas API.
Here's an example, based off of the code that you shared:
// canvas setup
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext('2d');
// 1st image
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0, 100, 100);
};
imageObj.src = 'https://s3.amazonaws.com/so-answers/image1.jpg';
// 2nd image
var thumbImageObj = new Image();
thumbImageObj.onload = function() {
// save current canvas state
ctx.save();
// perform transformation
ctx.translate(110,110);
ctx.rotate(20*Math.PI / 180);
ctx.drawImage(thumbImageObj, 0, 0, 100, 100);
// restore original canvas state (without rotation etc)
ctx.restore();
};
thumbImageObj.src = 'https://s3.amazonaws.com/so-answers/image2.jpg';
body {
overflow: hidden;
margin: 0;
padding: 0;
}
<canvas id="canvas"></canvas>

Related

Canvas not working when inside a for loop [duplicate]

I wanted to upload the image files, draw them into canvas, make changes and save it in the database. I tried to test the base64 value that the canvas image (Pic) returned, and it is blank. However, I see the result when I append the canvas (Pic) to the document. What am I doing wrong here?
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
// read contents of files asynchronously
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
var canvas = document.createElement("canvas");
var datauri = event.target.result,
ctx = canvas.getContext("2d"),
img = new Image();
img.onload = function() {
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
};
img.src = datauri;
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
document.body.appendChild(canvas); //picture gets uploaded
// Generate the image data
var Pic = canvas.toDataURL("image/png");
console.log(Pic); // => returns base64 value which when tested equivalent to blank
Pic = Pic.replace(/^data:image\/(png|jpg);base64,/, "")
// Sending image to Server
$.ajax({
// …
});
};
})(f);
reader.readAsDataURL(f);
}
}
My intuition says that everything from var imageData = … should go into the img.onload function.
That means, at the relevant part the code becomes:
img.onload = function() {
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
document.body.appendChild(canvas); //picture gets uploaded
// Generate the image data
var Pic = canvas.toDataURL("image/png");
console.log(Pic); // => returns base64 value which when tested equivalent to blank
Pic = Pic.replace(/^data:image\/(png|jpg);base64,/, "")
// Sending image to Server
$.ajax({
// …
});
};
img.src = datauri;
The reason is that the line
ctx.drawImage(img, 0, 0, width, height);
correctly executes after the image has been loaded. But unfortunately, you don’t wait for loading when this line gets executed:
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
and all subsequent lines.
The image needs to be loaded in order to draw it on the canvas. The canvas needs to contain the loaded image in order to call getImageData.
I found a better solution to get the base64 code
Instead of this line:
var Pic = canvas.toDataURL("image/png");
use this:
var Pic = canvas.toDataURL("image/png").split(',')[1];

Waterflow simulation through a pipe using Three.js

I want to simulate water flow through the pipe using Three.js in my React application. As you can see in the below picture, I want to achieve three functionalities,
Draw a pipe
Simulate water based on % (0-100) - Now pipe filled with 70% of water.(user-defined)
Animate water flow using arrows moving from left to right - (left to right/ right to left) - user-defined
Something I tried was not working
A hollow cylinder (pipe), based on ExtrudeGeometry:
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.133.1";
import {
OrbitControls
} from "https://cdn.skypack.dev/three#0.133.1/examples/jsm/controls/OrbitControls.js";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
camera.lookAt(scene.position);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let r = 1, R = 1.25;
// pipe
let pipeShape = new THREE.Shape();
pipeShape.absarc(0, 0, R, 0, Math.PI * 2);
pipeShape.holes.push(new THREE.Path().absarc(0, 0, r, 0, Math.PI * 2, true));
let pipeGeometry = new THREE.ExtrudeGeometry(pipeShape, {
curveSegments: 100,
depth: 10,
bevelEnabled: false
});
pipeGeometry.center();
let pipeMaterial = new THREE.MeshLambertMaterial({color: "silver"});
let pipe = new THREE.Mesh(pipeGeometry, pipeMaterial);
scene.add(pipe);
window.addEventListener("resize", onResize);
renderer.setAnimationLoop(_ => {
renderer.render(scene, camera);
})
function onResize(event) {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
</script>
It looks like your cylinder Geometry is oversized compared to your scene.
Watch the following example :
https://codepen.io/freddy-turtle/pen/OJjVmvG?editors=1010
the cylinder appear in the whole screen with CylinderGeometry = 1,1,3 as first arguments.

How do I add text to a image in Node Canvas?

So I have been looking all over the discord.js docs and tried to make a profile card with image manipulation, but for some reason the text comes up as little boxes. Here is the code:
if (message.content === `-profile`) {\
const Canvas = require(`canvas`);
const canvas = Canvas.createCanvas(700, 250);
const ctx = canvas.getContext('2d');
const background = await Canvas.loadImage('./image.png');
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
ctx.strokeStyle = '#74037b';
ctx.strokeRect(0, 0, canvas.width, canvas.height);
ctx.font = '100px sans-serif';
// Select the style that will be used to fill the text in
ctx.fillStyle = '#34ebc9';
// Actually fill the text with a solid color
ctx.fillText(message.author.displayName, canvas.width / 2.5, canvas.height / 1.8);
ctx.beginPath();
ctx.arc(125, 125, 100, 0, Math.PI * 2, true);
ctx.closePath();
ctx.clip();
const avatar = await Canvas.loadImage(message.author.displayAvatarURL({ format: 'jpg' }));
ctx.drawImage(avatar, 25, 25, 200, 200);
const attachment = new Discord.MessageAttachment(canvas.toBuffer(), 'welcome-image.png');
message.channel.send(`Your profile, ${message.author}!`, attachment);
}
The image shows and my profile picture shows and everything, but for some reason the text either doesn't show, or it is all messed up. Please help.
Your Device maybe doesn't have any default file that Canvas is looking for. You need to install these fonts manually by yourself, you can get some from Google Fonts.
Import the fonts you installed to your Files and use registerFont() to register and use the fonts
//Assume you imported your font in your main folder
const { registerFont, createCanvas } = require('canvas')
registerFont('./comicsans.ttf', { family: 'Comic Sans' })
const canvas = createCanvas(500, 500)
const ctx = canvas.getContext('2d')
ctx.font = '12px "Comic Sans"'
ctx.fillText('Everyone hates this font :(', 250, 10)

Three JS get curves on edges of cuboid (box geometry)

I am new to three.js and I used box geometry for drawing a concrete slab! I am trying to draw waves like shapes on edges of 3D rectangular slab. My requirement is some thing like this.
I don't know if its possible to achieve above curves with box geometry
You can distort a box geometry as much as you want.
If you want waves, then use sin or cos functions:
body {
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three#0.118.3/build/three.module.js";
import {OrbitControls} from "https://cdn.jsdelivr.net/npm/three#0.118.3/examples/jsm/controls/OrbitControls.js";
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(10, 10 ,10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new OrbitControls(camera, renderer.domElement);
var g = new THREE.BoxBufferGeometry(13, 5, 3, 20, 1, 1);
var p = g.getAttribute("position");
var v3 = new THREE.Vector3();
for(let i = 0; i < p.count; i++){
v3.fromBufferAttribute(p, i);
p.setZ(i, v3.z + Math.sin(v3.x));
}
g.computeVertexNormals();
var m = new THREE.MeshBasicMaterial({color: "aqua", wireframe: true});
var o = new THREE.Mesh(g, m);
scene.add(o);
renderer.setAnimationLoop(()=>{
renderer.render(scene, camera);
});
</script>

ThreeJs OBJLoader output looks very pixelated

I am trying to load .obj file through OBJLoader in angularjs. But the output is very pixelated.
Tried changing camera position & perspective(codes are commented), then it results in very smaller output, i need to zoom in through mouse in that case.But if i open the same .obj file in 3D Boulder or any other tools, it looks fine.
I have set camera & scene like this -
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvasRef.nativeElement });
// this.renderer.setSize( window.innerWidth, window.innerHeight );
// this.renderer.setSize(640, 720);
// scene
this.scene = new THREE.Scene();
this.renderer.setClearColor(0xcdcbcb, 1);
// camera
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000);
// this.camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.01, 10000);
this.camera.position.set(1, 1, 1);
// this.camera.position.set(0, 0, 1);
// this.camera.position.set(113, 111, 113);
this.camera.aspect = window.innerWidth / window.innerHeight;
this.scene.add(new THREE.AmbientLight(0x222222));
this.scene.add(this.camera); // required, because we are adding a light as a child of the camera
// controls
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
// lights
var light = new THREE.PointLight(0xffffff, 0.8);
this.camera.add(light);
var geometry = new THREE.BoxGeometry(1,1,1);
Loading .obj file like this -
var objLoader = new OBJLoader();
objLoader.load("../../assets/temp_data/11.obj", function (object) {
console.log(object);
this.scene.add(object);
}.bind(this));
this.animate();
what should be good camera & scene parameters so that it will work on all models & no need to zoom in or zoom out. Please Guide / Help.
this.renderer.setPixelRatio(window.devicePixelRatio);
this works for me.

Resources