这个问题与[一] [1]有些相关。我想要实现的是允许用户将多个文本图层和图像图层添加到单个网格中的方法。
我正在创建每个文本/图像作为使用自己的画布构建的自己的图层,如下所示:
getTextCanvas(textLayer) {
var textPositions, textXPos, textYPos, styleToAdd = '';
if(textLayer.bold) {
styleToAdd += ' bold ';
}
if(textLayer.italic) {
styleToAdd += ' italic '
}
var textCanvas = this.getCanvasTextureObject(textLayer.guid, 512, 512);
textCanvas.canvas.style.backgroundColor = 'red';
var ctx = textCanvas.ctx;
ctx.font = styleToAdd + " 12px arial";
var txtWidth = ctx.measureText(textLayer.text).width;
textXPos = (textCanvas.canvas.width / 2) - (txtWidth / 2);
textYPos = textCanvas.canvas.height / 2;
ctx.fillText(textLayer.text, textXPos, textYPos);
return textCanvas.canvas;
}
getCanvasTextureObject()
看起来像这样:
getCanvasTextureObject(id, width?, height?) {
var canvasEle = document.createElement('canvas');
canvasEle.id = id;
// When painted on the bag this style isn't honoured
canvasEle['style'].backgroundColor = 'red';
var ctx = canvasEle.getContext('2d');
var texture = new THREE.CanvasTexture(canvasEle);
return {
canvas: canvasEle,
ctx: ctx,
texture: texture
}
}
最后我将它全部添加到网格中,从画布纹理映射到Mesh Phong材质(我认为这是错误的材料,但也许是Shader?):
updateBag() {
if(!this.mainCanvas) {
this.mainCanvas = this.getCanvasTextureObject('main-canvas', 1024, 1024);
}
_.forEach(this.layers, (l) => {
this.mainCanvas.ctx.drawImage(l.canvas, 0, 0);
});
var canvasTexture = new THREE.CanvasTexture(this.mainCanvas.canvas);
var material = new THREE.MeshPhongMaterial({color: 0x00ff00, map: canvasTexture, transparent: true, overdraw: false, opacity: 1, depthTest: false });
this.selectedProduct[0]['children'][0].material.materials[1] = material;
}
我遇到的几个问题是:
那我在这里做错了什么?
由于
答案 0 :(得分:0)
Thanks to @TheJim01 for putting me on the right path. The key, as described above was to ensure that each side is unique and added to one texture.
For me I wanted the option of adding either text or an image to any side of my object and not have them overwrite each other. First - each side of the object is an array. In that array we can have many objects, each one represents either a text or an image layer:
layers = {
front: [],
back: [],
left: [],
right: [],
base: [],
top: []
};
Then when any of these arrays are modified I would redraw that side of the object by creating a canvas, assigning that canvas to a Texture
and ensuring that each drawn image is the same size (if not then the text or the image will appear pixelated):
updateBag() {
if(this.selectedProduct) {
var mainCanvas, canvasTexture;
var sidesModified = this.getSidesModified();
var side, sides = _.keys(sidesModified);
for(var i = 0; i < sides.length; i++) {
side = sides[i];
mainCanvas = this.getCanvas('main-canvas', 'main');
canvasTexture = new THREE.Texture(mainCanvas.canvas);
for(var j = 0; j < this.layers[side].length; j++) {
if(side === 'front' || side === 'back'){
canvasTexture.wrapS = THREE.RepeatWrapping;
canvasTexture.repeat.x = -1;
}
mainCanvas.ctx.drawImage( this.layers[side][j].canvas, 0, 0, this.canvasWidth, this.canvasHeight);
}
var material = new THREE.MeshBasicMaterial({map: canvasTexture, side: THREE.FrontSide, transparent: false});
this.setMaterialToBag(material, side);
canvasTexture.needsUpdate = true;
}
}
}