I'm doing a simple project with Physics.JS and I want to be able to add text to a PhysicsJS World. I looked in the documentation but I couldn't find something that can allow me to do such thing. Is there a way to add text and to also be able to manipulate parts of it, like increasing velocity, restitution and other things from the engine?
Just extend a rectangle body, and change its view to a canvas with text on it:
Physics.body('text', 'rectangle', function (parent) {
var canv = document.createElement('canvas');
canv.width = 310;
canv.height = 60;
var ctx = canv.getContext("2d");
ctx.fillStyle = "#ffffff";
ctx.textAlign = "left"
ctx.textBaseline = "top";
ctx.font = "80px sans-serif";
return {
// Called when the body is initialized
init: function(options) {
parent.init.call(this, options);
ctx.fillText(options.text,0,0);
},
// Called when the body is added to a world
connect: function() {
this.view = canv;
}
}
});
Then, to instantiate it:
Physics.body('text', {
x: 400,
y: 570,
width: 310,
height: 60,
text: "Some text here",
})
You specify the string of text via options.text.
Of-course, one would make it more dynamic, by allowing to specify the font parameters in the options, then auto-calculate the dimension on init, and so on...
Related
<script>
// (B) IMAGES + CANVAS
var iBack = new Image(),
iMark = "long text",
canvas = document.getElementById("demo"),
ctx = canvas.getContext("2d");
// (C) WATERMARK
function cmark () {
// (C1) ADD BACKGROUND IMAGE
canvas.width = iBack.naturalWidth;
canvas.height = iBack.naturalHeight;
ctx.drawImage(iBack, 100, 100, iBack.naturalWidth, iBack.naturalHeight);
// (C2) ADD WATERMARK
ctx.font = "bold 24px Arial";
ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
ctx.fillText(iMark, 10, 100);
ctx.fillText("width:" + ctx.measureText(iMark).width, 100, 50);
/* (C3) DOWNLOAD (IF YOU WANT)
let anchor = document.createElement("a");
anchor.href = canvas.toDataURL("image/png");
anchor.download = "marked.png";
anchor.click();
anchor.remove();*/
}
// (D) GO - PROCEED ONLY WHEN IMAGES ARE LOADED
iBack.onload = cmark;
iBack.src = "image.jpg";
</script>
When I write long text, it takes it out of the picture. I don't want it to spill out of the picture. How can I fix the canvas text overflowing the image? Can you help me?
You can draw only one line of text at a time with filltext(), so you need to split you text into several parts when it's too long. You can use measureText(iMark)to measure the length of you text, :
if (measureText(iMark)>100) {
let temp1 = iMark.slice(0,iMark.length/2);
let temp2 = iMark.slice(iMark.length/2,iMark.length);
ctx.fillText(temp1, 10, 100);
ctx.fillText(temp1, 10, 200);
}
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 am using fillRect to draw rectangular in canvas. I want to add text I want it to be editable like edit box. Is there a way to achieve this in JavaScript?
I don't want fillText because I want the text to be editable on canvas.
For sure! (Although it's tricky)
Thankfully someone has already done it and posted it in a Github repository: https://github.com/goldfire/CanvasInput
It is under the MIT Licence, so make sure to abide by its conditions!
It can be done, but don't!!!
This is the most basic of examples. I do not recommend that anyone do this unless it is for their own use, and that they have strict control over the browser and the browser version, localisation, and more. This will break for more reasons then there are lines of code.
canvasTextBox defines all that is needed. It creates a HTMLInputElement and then listens to the keyup and input events.
An animation loop checks for any change in state and renders the text if needed, in sync with all other DOM rendering.
I have added a basic blinking cursor, but no selection of text, no insert, overwrite modes, no writing direction (left to right only), no spell checking, no no, and no.
I have added no focus checking, no way to turn it off, there is no mouse interaction, and no context menu.
To implement just a basic usable public version using this method would need well over 1000 lines of code, and months of testing. Even then it will not always work as there will always be some special case that is unknowable from within the JavaScript context.
Canvas textbox
Example works on Chrome beta on a Win10 machine, may work on other browsers/OS but I have not bothered to check.
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 200;
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var globalTime; //
var canvasTextBox = {
x : 10,
y : 10,
h : 50,
w : 300,
ready : false,
font : "40px arial",
fontCol : "blue",
selectColour : "blue",
background : "#CCC",
border : "black 2px", // this is not a CSS style and will break if you dont have colour and width
create : function(){
var text = document.createElement("input")
text.type = "text";
text.style.position = "absolute";
var bounds = canvas.getBoundingClientRect();
text.style.top = (bounds.top + this.x + 2) + "px";
text.style.left = (bounds.left + this.y +2 )+ "px";
text.style.zIndex = -100;
document.body.appendChild(text);
this.textState.element = text;
// get some events
this.textState.events = (function(event){
this.changed = true;
this.text = this.element.value;
}).bind(this.textState);
// add a blink thing
this.textState.blink = (function(){
this.cursorOn = !this.cursorOn;
this.changed = true;
setTimeout(this.blink,this.cursorRate);
}).bind(this.textState);
// listen for changes
text.addEventListener("input",this.textState.events);
text.addEventListener("keyup",this.textState.events);
this.ready = true;
},
render : function(){
var start,end;
ctx.font = this.font;
ctx.fillStyle = "#AAA";
ctx.strokeStyle = this.border.split(" ")[0];
ctx.lineWidth = this.border.split(" ")[1].replace("px","");
ctx.fillRect(this.x,this.y,this.w,this.h);
ctx.strokeRect(this.x,this.y,this.w,this.h);
ctx.fillStyle = this.fontCol;
start = 0;
end = 0;
if(this.textState.element.selectionStart !== undefined){
start = this.textState.element.selectionStart;
}
var text = this.textState.text;
var textStart = text.substr(0,start);
var w = ctx.measureText(text).width;
var wStart = ctx.measureText(textStart).width;
var cursor = this.x + wStart;
ctx.save();
ctx.beginPath();
ctx.rect(this.x,this.y,this.w,this.h);
ctx.clip();
if(w > this.w){
cursor = this.x + this.w - w + wStart;
if(cursor < this.x){
ctx.fillText(this.textState.text,this.x+this.w-w + (this.x - cursor)+3,this.y + 40);
cursor = this.x;
}else{
ctx.fillText(this.textState.text,this.x+this.w-w,this.y + 40);
}
}else{
ctx.fillText(this.textState.text,this.x,this.y + 40);
}
if(this.textState.cursorOn){
ctx.fillStyle = "red";
ctx.fillRect(cursor,this.y,3,this.h);
}
ctx.restore();
},
textState : {
text : "",
cursor : 0,
cursorOn : false,
cursorRate : 250,
changed : true,
events : null,
element : null,
},
update : function(){
if(this.textState.changed){
this.textState.changed = false;
this.render();
}
},
focus : function(){
this.textState.element.focus();
this.textState.blink();
},
}
canvasTextBox.create();
canvasTextBox.focus();
// main update function
function update(timer){
globalTime = timer;
if(canvasTextBox.ready){
canvasTextBox.update();
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
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
I want to develop extension for magento which help to create custom t-shirt but i don't know how to do it.I want to provide functionality like this site http://www.inkpixi.com/item/ATV+Repair/A252/329/item.htmlDead link
here you enter the name and then name automatically insert to image .i want to provide this exactly but didn't get right matter
You can do it so simply with canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = 200;
canvas.height = 200;
document.body.appendChild(canvas);
function sendToCanvas( ob ){
var img = new Image();
img.addEventListener('load', function(){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.font = ob.fontWeight+' '+ob.fontSize+' '+ob.fontFamily;
ctx.textAlign = 'center';
ctx.fillStyle = ob.color;
ctx.fillText(ob.text, canvas.width/2, canvas.height/2.5);
});
img.src = ob.image;
}
// Defaults
var cvsObj = {
text : "stackoverflow",
image : "http://i.imgur.com/hqayV16.jpg",
fontFamily : "Arial",
fontWeight : "bold",
fontSize : "90%",
color : "rgba(244, 128, 36, 0.7)"
};
sendToCanvas( cvsObj ); // Send default data on init
document.getElementById("text").addEventListener("input", function(){
cvsObj.text = this.value; // Modify cvsObj text
sendToCanvas( cvsObj ); // Send custom data on input
});
Text: <input id="text" type="text"><br>
Right click and Save as :) !