• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Finding the coordinates of a given letter using html5 canvas

Community Beginner ,
Dec 13, 2022 Dec 13, 2022

Copy link to clipboard

Copied

hi,

in flash cs using as3 to find the position of a character we used getCharBoundaries(index).x is it possible to find a character of a label.innerHTML using adobe animate html5 canvas?? thanks.

Views

999

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Dec 15, 2022 Dec 15, 2022

create a movieclip that contains a textfield.  right align the text if you're going to use right-to-left language like arabic, left align the text for left-to-right languages.  assign the textfield an instance name, eg tf.  assign the movieclip a linkage id, eg tf_mc.

 

your can then use:

 

// [word or phrase to be display, character index where bin should be placed for a correct answer]var wordA = [["first word",2],["second word",5]];
var index,i,mc;

 

// add your drag and drop listeners. bind(

...

Votes

Translate

Translate
Community Expert ,
Dec 21, 2022 Dec 21, 2022

Copy link to clipboard

Copied

you can use textmetrics, https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics

 

eg,

 

this.tf.text = "ab cd ef gh ij kl mn";  // tf is on stage textfield;

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

 

var tm = ctx.measureText("a");
console.log(tm.width,tm.actualBoundingBoxLeft,tm.actualBoundingBoxRight);

 

tm = ctx.measureText("mn");
console.log(tm.width,tm.actualBoundingBoxLeft,tm.actualBoundingBoxRight);

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 18, 2022 Dec 18, 2022

Copy link to clipboard

Copied

there's no way to finding Bounds() for letter in the text without split it ??

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 18, 2022 Dec 18, 2022

Copy link to clipboard

Copied

there might be but it would take significantly more time, for me, to develop.

 

can you answer : if letters are connected, how do arabic typewriters work?  eg, if you type (in arabic ) a letter you would see one kind of glyph and then if you type another, the first glyph has to change, doesn't it?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 18, 2022 Dec 18, 2022

Copy link to clipboard

Copied

yes, when we type ع and then Ù†  the first letter change to عن then عنك  and then عنكب then عنكبو and so on

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Dec 13, 2022 Dec 13, 2022

Copy link to clipboard

Copied

Not by any reasonable means, no. If you want the position of an individual character, you have to make the character an individual object.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 13, 2022 Dec 13, 2022

Copy link to clipboard

Copied

unfortunately,it's an impractical solution  because there is alot of words inside the website also it's an arabic words the width changed when the letter inside the word or it inside an individual object

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 22, 2022 Dec 22, 2022

Copy link to clipboard

Copied

Hi.

 

This is just a suggestion that I hope will help you to get started.

 

It doesn't work perfectly with arabic texts unfortunately. This is because in arabic texts two (or more?) letters are usually combined together and this makes the calculations very hard.

 

Special characters may overflow as well.

 

It's not the most efficient way of doing this and also the bounding boxes will need some workaround to remain invisible.

 

Again, I just want to provide a sample of what it is possible by only using the CreateJS API. Maybe it's possible to do more using the canvas API.

 

Try it:
https://bit.ly/3WEJHtm

 

Javascript:

[Global script]:

(function()
{
	window.ui = {};

	// text boxes
	ui.TextBoxes = function(target)
	{
		this.target = target;
		this.setBoundingBoxes();
	}

	ui.TextBoxes.prototype.setBoundingBoxes = function()
	{
		var originalText = this.target.text;
		var originalMetrics = this.target.getMetrics();
		var currentWidth = originalMetrics.width;
		var lines = originalMetrics.lines;
		var totalLines = lines.length;
		var lettersWidthSum = 0;
		var totalLinesLetters, letterMetrics, i, j;
		var boundingBox = {};	
		var alignOffset = this.getAlignmentOffset(this.target);
		
		this.target.text = "";
		this.target.boundingBoxes = [];
		
		for (i = 0; i < totalLines; i++)
		{
			totalLinesLetters = lines[i].length;
			lettersWidthSum = 0;
			this.target.text = lines[i];
			currentWidth = this.target.getMetrics().width;
			
			for (j = 0; j < totalLinesLetters; j++)
			{
				this.target.text = lines[i][j];
				letterMetrics = this.target.getMetrics();
				boundingBox = this.drawBoundingBox(letterMetrics.width, letterMetrics.height);
				boundingBox.x = this.target.x + lettersWidthSum - currentWidth * alignOffset;
				boundingBox.y = this.target.y + letterMetrics.lineHeight * i;
				boundingBox.setBounds(boundingBox.x, boundingBox.y, letterMetrics.width, letterMetrics.height);
				boundingBox.alpha = 0.2;
				boundingBox.tf = this.target;
				this.target.parent.addChild(boundingBox);
				lettersWidthSum += letterMetrics.width;
				this.target.boundingBoxes.push(boundingBox);
			}
		}

		this.target.text = originalText;
	};

	ui.TextBoxes.prototype.drawBoundingBox = function(width, height)
	{
		var shape = new createjs.Shape();
		
		shape.graphics.beginFill("rgba(255,255,255,0.1)");
		shape.graphics.beginStroke("rgba(255,255,255,1)");
		shape.graphics.setStrokeStyle(1);
		shape.graphics.drawRect(0, 0, width, height);
		shape.graphics.endFill();
		shape.graphics.endStroke();
		
		return shape;
	}

	ui.TextBoxes.prototype.getAlignmentOffset = function()
	{
		if (this.target.textAlign === "left")
			return 0;
		
		if (this.target.textAlign === "center")
			return 0.5;
		
		if (this.target.textAlign === "right")
			return 1;
	};

	ui.TextBoxes.prototype.destroy = function()
	{
		if (!this.target.boundingBoxes)
			return;
		
		this.target.boundingBoxes.forEach(function(boundingBox)
		{
			boundingBox.parent.removeChild(boundingBox);
			boundingBox._off = true;
		});
		
		delete this.target.boundingBoxes;
	};


	// drag and drop
	ui.DragAndDrop = function(target, callbacks)
	{
		this.target = target;
		this.callbacks = callbacks || {};
		this.mouseDownListener = this.target.on("mousedown", this.onMouseDown, this);
		this.pressMoveListener = this.target.on("pressmove", this.onPressMove, this);
		this.pressUpListener = this.target.on("pressup", this.onPressUp, this);
	};

	ui.DragAndDrop.prototype.onMouseDown = function(e)
	{
		var pointer = this.getPointer(this.target);
		
		this.target.offset = { x: pointer.x - this.target.x, y: pointer.y - this.target.y };
		this.target.parent.addChild(this.target);
		
		if (this.callbacks.onMouseDown)
			this.callbacks.onMouseDown.call(this);
	};

	ui.DragAndDrop.prototype.onPressMove = function(e)
	{
		var pointer = this.getPointer(this.target);
		
		this.target.x = pointer.x - this.target.offset.x;
		this.target.y = pointer.y - this.target.offset.y;
		
		if (this.callbacks.onPressMove)
			this.callbacks.onPressMove.call(this);
	};

	ui.DragAndDrop.prototype.onPressUp = function(e)
	{		
		if (this.callbacks.onPressUp)
			this.callbacks.onPressUp.call(this);
	};

	ui.DragAndDrop.prototype.getPointer = function(target)
	{
		return target.parent.globalToLocal(target.stage.mouseX, target.stage.mouseY);
	};

	ui.DragAndDrop.prototype.destroy = function()
	{
		this.target.off("mousedown", this.mouseDownListener);
		this.target.off("pressmove", this.pressMoveListener);
		this.target.off("pressup", this.pressUpListener);	
		
		delete this.target;
		delete this.callbacks;
	};
})();


[Frame 0 of main timeline]:

// the TextBoxes and DragAndDrop classes are located in the globa script section (left sections)

var callbacks =
{
	onMouseDown: function()
	{
		this.target.mouseEnabled = false;
	},
	onPressUp: function()
	{
		var box = this.currentBoundingBox;
		
		this.target.mouseEnabled = true;
		
		if (box && box.correct !== undefined)
		{
			drawBoundingBox(box);
			
			this.target.x = box.x + box.getBounds().width * 0.5;
			this.target.y = box.y - this.target.nominalBounds.height * 0.5;
			
			box.tf.dragAndDrop.destroy();
			box.tf.textBoxes.destroy();
			
			box = null;
		}
		else
		{
			this.target.x = this.target.initialX;
			this.target.y = this.target.initialY;
		}
	}
};

function main()
{
	var resetTarget0 = { tf: root.tf0, bin: root.bin0, correct: 1, slot: root.slot0 };
	var resetTarget1 = { tf: root.tf1, bin: root.bin1, correct: 0, slot: root.slot1 };
	var resetTarget2 = { tf: root.tf2, bin: root.bin2, correct: 2, slot: root.slot2 };

	setup();
	setGame(root.tf0, root.bin0, 1, root.slot0);
	setGame(root.tf1, root.bin1, 0, root.slot1);
	setGame(root.tf2, root.bin2, 2, root.slot2);
	root.resetButton0.on("click", onReset, null, false, resetTarget0);
	root.resetButton1.on("click", onReset, null, false, resetTarget1);
	root.resetButton2.on("click", onReset, null, false, resetTarget2);
	root.resetAllButton.on("click", onResetAll, null, false, { targets: [ resetTarget0, resetTarget1, resetTarget2 ] });
}

function setup()
{
	document.body.style.backgroundColor = lib.properties.color;
	createjs.Touch.enable(stage);
	stage.enableMouseOver(50);
	stage.mouseMoveOutside = true;
	root.stop();
}

function setGame(tf, bin, correct, slot)
{
	tf.textBoxes = new ui.TextBoxes(tf);
	tf.boundingBoxes[correct].correct = true;
	
	tf.boundingBoxes.forEach(function(boundingBox)
	{
		boundingBox.mouseOverListener = boundingBox.on("mouseover", onMouseOver);
		boundingBox.mouseOutListener = boundingBox.on("mouseout", onMouseOut);
	});

	tf.dragAndDrop = new ui.DragAndDrop(bin, callbacks);
	bin.initialX = slot.x;
	bin.initialY = slot.y;
}

function onMouseOver(e)
{
	e.currentTarget.alpha = 1;
	e.currentTarget.tf.dragAndDrop.currentBoundingBox = e.currentTarget;
}

function onMouseOut(e)
{
	e.currentTarget.alpha = 0.2;
	e.currentTarget.tf.dragAndDrop.currentBoundingBox = null;
}

function drawBoundingBox(box)
{
	box.tf.winBox = new createjs.Shape();
	box.tf.winBox.graphics.beginFill("rgba(255,255,255,0.5)");
	box.tf.winBox.graphics.beginStroke("white");
	box.tf.winBox.graphics.setStrokeStyle(2);
	box.tf.winBox.graphics.drawRect(0, 0, box.getBounds().width, box.getBounds().height);
	box.tf.winBox.graphics.endFill();
	box.tf.winBox.graphics.endStroke();
	box.tf.winBox.x = box.x;
	box.tf.winBox.y = box.y;
	box.tf.parent.addChild(box.tf.winBox);
}

function onReset(e, data)
{
	if (data.tf.dragAndDrop.target)
		data.tf.dragAndDrop.destroy();
	
	if (data.tf.textBoxes.target)
		data.tf.textBoxes.destroy();
	
	root.addChild(data.bin);
	data.bin.x = data.slot.x;
	data.bin.y = data.slot.y;
	
	if (data.tf.winBox && data.tf.winBox.parent)
	{
		data.tf.winBox.parent.removeChild(data.tf.winBox);
		data.tf.winBox._off = true;
	}
	
	setGame(data.tf, data.bin, data.correct, data.slot);
}

function onResetAll(e, data)
{
	data.targets.forEach(function(target){ onReset(null, target); });
}

if (!this.frame0started)
{
	window.root = this;
	main();
	this.frame0started = true;
}

 

Code / FLA / files / source:
https://bit.ly/3BWEx3S

 

I hope it helps.

 

Regards,

JC

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 26, 2022 Dec 26, 2022

Copy link to clipboard

Copied

LATEST

thank's alot 🙂

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines