w3d
Version:
Framework to create 3D web pages.
119 lines (91 loc) • 3.04 kB
JavaScript
/*
* word2d.js
* Copyright 2017 Lucas Neves <lcneves@gmail.com>
*
* Exports an object that contains letter sprites.
* Part of the w3d project.
*/
;
const THREE = require('three');
const windowUtils = require('./window-utils.js');
const objectCommons = require('./object-commons.js');
const objectUtils = require('./object-utils.js');
const Object3D = require('./object3d.js');
const cache = require('./cache.js');
function makeTexture (character, style) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = style.fontSize + 'px ' + style.fontFamily;
canvas.width = ctx.measureText(character).width;
canvas.height = style.fontSize * 1.2; // fontsize * 1.5
// after setting the canvas width/height we have to re-set font to apply!?
// looks like ctx reset
ctx.font = style.fontSize + 'px ' + style.fontFamily;
ctx.fillStyle = 'white';
ctx.fillText(character, 0, style.fontSize, canvas.width);
var texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.LinearFilter; // NearestFilter;
return texture;
}
function getTextureFromCache (character, style) {
var styleMinusColor = JSON.parse(JSON.stringify(style));
delete styleMinusColor.color; // Not important for texture
var descriptor = {
character: character,
style: styleMinusColor,
type: 'text2d'
};
var texture = cache.fetch(descriptor);
if (!texture) {
texture = makeTexture(character, style);
cache.insert(texture, descriptor);
}
return texture;
}
class CharSprite extends THREE.Sprite {
constructor (spriteMaterial) {
super(spriteMaterial);
this._isSpriteFromCanvas = true;
}
}
const charSpritePrototype = {
resize () {
var width = this.material.map.image.width;
var aspect = width / this.material.map.image.height;
var scaleFactor = windowUtils.getFontScaleFactor(width);
this.scale.set(scaleFactor, scaleFactor / aspect, 1);
this.w3dAllNeedUpdate();
}
};
objectUtils.importPrototype(CharSprite.prototype, objectCommons);
objectUtils.importPrototype(CharSprite.prototype, charSpritePrototype);
class Word2D extends Object3D {
// Style could be built for each new word, but it is more practical to
// make it only once for the whole paragraph.
constructor (word, style, parentObject) {
if (!word) {
throw new Error('Invalid word!');
}
super({ setParent: parentObject });
this._isWord2D = true;
this._originalWorldToPixels = windowUtils.worldToPixels;
this._ht3d = {
tag: 'word',
class: '',
id: ''
};
this.makeStyle();
this._style['margin-right'] = this.getStyle('word-spacing');
var charArray = word.split('');
for (let character of charArray) {
let material = new THREE.SpriteMaterial({
map: getTextureFromCache(character, style),
color: style.color
});
let sprite = new CharSprite(material);
sprite.resize();
this.add(sprite);
}
}
}
module.exports = Word2D;