за три. js Лучше всего, чтобы текстуры были степенью 2, а на самом деле это требование для некоторых старых Chrome браузеров, например, 32x32, 64x64 и c
Поэтому мне нужно чтобы создать холст текстуру с силой в 2 измерения, но мне нужно, чтобы спрайт был кликабельным, что означает, что его нужно как-то обрезать.
Рассмотрим этот пример:
- Черный bg - это тройка. js рендер
- Красный bg - требуемый размер холста (до степени 2)
- White bg - это размер текста
Я хотел бы сохранить текстуру в степени 2, но обрезать ее, чтобы показать только белую область. Это так, например, пользователь может навести курсор на ярлык. Я не хочу, чтобы они зависали на красной территории!
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 400;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var config = {
fontface: 'Arial',
fontsize: 32,
fontweight: 500,
lineheight: 1,
};
var text = 'Hello world!';
function nextPowerOf2(n) {
return Math.pow(2, Math.ceil(Math.log(n) / Math.log(2)));
}
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
const textMetrics = ctx.measureText(text);
var textWidth = textMetrics.width;
var textHeight = config.fontsize * config.lineheight;
canvas.width = nextPowerOf2(textWidth);
canvas.height = nextPowerOf2(textHeight);
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, textWidth, textHeight);
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
ctx.fillText(text, 0, 0);
console.log('canvas', canvas.width, canvas.height);
console.log('text', textWidth, textHeight);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var spriteMaterial = new THREE.SpriteMaterial({
map: texture
});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(spriteMaterial.map.image.width, spriteMaterial.map.image.height, 1);
scene.add(sprite);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
body { margin: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
Как это возможно? Каким-то образом обрезать SpriteMaterial?