提交 95c1a08a 编写于 作者: M Mugen87

TTFLoader: Refactoring

上级 05207c5b
/**
* @author gero3 / https://github.com/gero3
* @author tentone / https://github.com/tentone
* Requires opentype.js to be included in the project
*
* Requires opentype.js to be included in the project.
* Loads TTF files and converts them into typeface JSON that can be used directly
* to create THREE.Font objects
* to create THREE.Font objects.
*/
'use strict';
THREE.TTFLoader = function ( manager ) {
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
......@@ -15,179 +14,179 @@ THREE.TTFLoader = function ( manager ) {
};
THREE.TTFLoader.prototype.load = function ( url, onLoad, onProgress, onError ) {
var scope = this;
THREE.TTFLoader.prototype = {
var loader = new THREE.FileLoader( this.manager );
loader.setResponseType( 'arraybuffer' );
loader.load( url, function ( buffer ) {
constructor: THREE.TTFLoader,
if ( onLoad !== undefined ) {
load: function ( url, onLoad, onProgress, onError ) {
onLoad( scope.parse( buffer ) );
}
var scope = this;
}, onProgress, onError );
var loader = new THREE.FileLoader( this.manager );
loader.setResponseType( 'arraybuffer' );
loader.load( url, function ( buffer ) {
};
onLoad( scope.parse( buffer ) );
THREE.TTFLoader.prototype.parse = function ( arraybuffer ) {
}, onProgress, onError );
if ( typeof opentype === 'undefined' ) {
},
console.warn( 'TTFLoader requires opentype.js Make sure it\'s included before using the loader' );
return null;
parse: function ( arraybuffer ) {
}
function convert( font, reversed ) {
function convert( font, reversed ) {
var round = Math.round;
var round = Math.round;
var glyphs = {};
var scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 );
var glyphs = {};
var scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 );
for ( var i = 0; i < font.glyphs.length; i ++ ) {
for ( var i = 0; i < font.glyphs.length; i ++ ) {
var glyph = font.glyphs.glyphs[ i ];
var glyph = font.glyphs.glyphs[ i ];
if ( glyph.unicode !== undefined ) {
if ( glyph.unicode !== undefined ) {
var token = {
ha: round( glyph.advanceWidth * scale ),
x_min: round( glyph.xMin * scale ),
x_max: round( glyph.xMax * scale ),
o: ''
};
var token = {
ha: round( glyph.advanceWidth * scale ),
x_min: round( glyph.xMin * scale ),
x_max: round( glyph.xMax * scale ),
o: ''
};
if ( reversed ) {
if ( reversed ) {
glyph.path.commands = reverseCommands( glyph.path.commands );
glyph.path.commands = reverseCommands( glyph.path.commands );
}
}
glyph.path.commands.forEach( function ( command, i ) {
glyph.path.commands.forEach( function ( command, i ) {
if ( command.type.toLowerCase() === 'c' ) {
if ( command.type.toLowerCase() === 'c' ) {
command.type = 'b';
command.type = 'b';
}
}
token.o += command.type.toLowerCase() + ' ';
token.o += command.type.toLowerCase() + ' ';
if ( command.x !== undefined && command.y !== undefined ) {
if ( command.x !== undefined && command.y !== undefined ) {
token.o += round( command.x * scale ) + ' ' + round( command.y * scale ) + ' ';
token.o += round( command.x * scale ) + ' ' + round( command.y * scale ) + ' ';
}
}
if ( command.x1 !== undefined && command.y1 !== undefined ) {
if ( command.x1 !== undefined && command.y1 !== undefined ) {
token.o += round( command.x1 * scale ) + ' ' + round( command.y1 * scale ) + ' ';
token.o += round( command.x1 * scale ) + ' ' + round( command.y1 * scale ) + ' ';
}
}
if ( command.x2 !== undefined && command.y2 !== undefined ) {
if ( command.x2 !== undefined && command.y2 !== undefined ) {
token.o += round( command.x2 * scale ) + ' ' + round( command.y2 * scale ) + ' ';
token.o += round( command.x2 * scale ) + ' ' + round( command.y2 * scale ) + ' ';
}
}
} );
} );
glyphs[ String.fromCharCode( glyph.unicode ) ] = token;
glyphs[ String.fromCharCode( glyph.unicode ) ] = token;
}
}
return {
glyphs: glyphs,
familyName: font.familyName,
ascender: round( font.ascender * scale ),
descender: round( font.descender * scale ),
underlinePosition: font.tables.post.underlinePosition,
underlineThickness: font.tables.post.underlineThickness,
boundingBox: {
xMin: font.tables.head.xMin,
xMax: font.tables.head.xMax,
yMin: font.tables.head.yMin,
yMax: font.tables.head.yMax
},
resolution: 1000,
original_font_information: font.tables.name
};
}
return {
glyphs: glyphs,
familyName: font.familyName,
ascender: round( font.ascender * scale ),
descender: round( font.descender * scale ),
underlinePosition: font.tables.post.underlinePosition,
underlineThickness: font.tables.post.underlineThickness,
boundingBox: {
xMin: font.tables.head.xMin,
xMax: font.tables.head.xMax,
yMin: font.tables.head.yMin,
yMax: font.tables.head.yMax
},
resolution: 1000,
original_font_information: font.tables.name
};
function reverseCommands( commands ) {
}
var paths = [];
var path;
function reverseCommands( commands ) {
commands.forEach( function ( c ) {
var paths = [];
var path;
if ( c.type.toLowerCase() === 'm' ) {
commands.forEach( function ( c ) {
path = [ c ];
paths.push( path );
if ( c.type.toLowerCase() === 'm' ) {
} else if ( c.type.toLowerCase() !== 'z' ) {
path = [ c ];
paths.push( path );
path.push( c );
} else if ( c.type.toLowerCase() !== 'z' ) {
}
path.push( c );
} );
}
var reversed = [];
} );
paths.forEach( function ( p ) {
var reversed = [];
var result = {
type: 'm',
x: p[ p.length - 1 ].x,
y: p[ p.length - 1 ].y
};
paths.forEach( function ( p ) {
reversed.push( result );
var result = {
type: 'm',
x: p[ p.length - 1 ].x,
y: p[ p.length - 1 ].y
};
for ( var i = p.length - 1; i > 0; i -- ) {
reversed.push( result );
var command = p[ i ];
var result = { type: command.type };
for ( var i = p.length - 1; i > 0; i -- ) {
if ( command.x2 !== undefined && command.y2 !== undefined ) {
var command = p[ i ];
var result = { type: command.type };
result.x1 = command.x2;
result.y1 = command.y2;
result.x2 = command.x1;
result.y2 = command.y1;
if ( command.x2 !== undefined && command.y2 !== undefined ) {
} else if ( command.x1 !== undefined && command.y1 !== undefined ) {
result.x1 = command.x2;
result.y1 = command.y2;
result.x2 = command.x1;
result.y2 = command.y1;
result.x1 = command.x1;
result.y1 = command.y1;
} else if ( command.x1 !== undefined && command.y1 !== undefined ) {
}
result.x1 = command.x1;
result.y1 = command.y1;
result.x = p[ i - 1 ].x;
result.y = p[ i - 1 ].y;
reversed.push( result );
}
result.x = p[ i - 1 ].x;
result.y = p[ i - 1 ].y;
reversed.push( result );
} );
}
return reversed;
} );
}
return reversed;
if ( typeof opentype === 'undefined' ) {
}
console.warn( 'THREE.TTFLoader: The loader requires opentype.js. Make sure it\'s included before using the loader.' );
return null;
return convert( opentype.parse( arraybuffer ), this.reversed );
}
return convert( opentype.parse( arraybuffer ), this.reversed );
}
};
......@@ -5,16 +5,14 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body
{
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info
{
#info {
position: absolute;
top: 10px;
width: 100%;
......@@ -22,8 +20,7 @@
z-index: 100;
display:block;
}
#info a, .button
{
#info a {
color: #f00;
font-weight: bold;
text-decoration: underline;
......@@ -33,15 +30,12 @@
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/utils/GeometryUtils.js"></script>
<script src="js/Detector.js"></script>
<script src="js/loaders/TTFLoader.js"></script>
<script src="js/libs/opentype.min.js"></script>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - TTFLoader using opentype by gero3
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - TTFLoader using opentype by gero3
<br/>type to enter new text, drag to spin the text
<br/><span class="button" id="color">change color</span>,
<span class="button" id="bevel">change bevel</span>
</div>
......@@ -49,28 +43,21 @@
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
THREE.Cache.enabled = true;
var container, hex, color;
var container, color;
var camera, cameraTarget, scene, renderer;
var group, textMesh1, textMesh2, textGeo, material;
var firstLetter = true;
var text = "three.js",
var text = 'three.js',
height = 20,
size = 70,
hover = 30,
curveSegments = 4,
bevelThickness = 2,
bevelSize = 1.5,
bevelSegments = 3,
bevelEnabled = true;
bevelSegments = 3;
var font = null;
var mirror = true;
var targetRotation = 0;
......@@ -85,14 +72,6 @@
init();
animate();
function decimalToHex( d ) {
var hex = Number( d ).toString( 16 );
hex = "000000".substr( 0, 6 - hex.length ) + hex;
return hex.toUpperCase();
}
function init() {
container = document.createElement( 'div' );
......@@ -118,37 +97,9 @@
var pointLight = new THREE.PointLight( 0xffffff, 1.5 );
pointLight.position.set( 0, 100, 90 );
pointLight.color.setHSL( Math.random(), 1, 0.5 );
scene.add( pointLight );
// Get text from hash
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) {
var colorhash = hash.substring( 0, 6 );
var fonthash = hash.substring( 6, 7 );
var weighthash = hash.substring( 7, 8 );
var bevelhash = hash.substring( 8, 9 );
var texthash = hash.substring( 10 );
hex = colorhash;
pointLight.color.setHex( parseInt( colorhash, 16 ) );
fontName = reverseFontMap[ parseInt( fonthash ) ];
fontWeight = reverseWeightMap[ parseInt( weighthash ) ];
bevelEnabled = parseInt( bevelhash );
text = decodeURI( texthash );
} else {
pointLight.color.setHSL( Math.random(), 1, 0.5 );
hex = decimalToHex( pointLight.color.getHex() );
}
material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
group = new THREE.Group();
......@@ -159,8 +110,7 @@
var loader = new THREE.TTFLoader();
loader.load( 'fonts/ttf/kenpixel.ttf', function ( json ) {
font = new THREE.Font(json);
//scene.add( font );
font = new THREE.Font( json );
createText();
} );
......@@ -188,23 +138,8 @@
document.addEventListener( 'keypress', onDocumentKeyPress, false );
document.addEventListener( 'keydown', onDocumentKeyDown, false );
document.getElementById( "color" ).addEventListener( 'click', function() {
pointLight.color.setHSL( Math.random(), 1, 0.5 );
hex = decimalToHex( pointLight.color.getHex() );
}, false );
document.getElementById( "bevel" ).addEventListener( 'click', function(){
bevelEnabled = !bevelEnabled;
refreshText();
}, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
......@@ -224,7 +159,7 @@
if ( firstLetter ) {
firstLetter = false;
text = "";
text = '';
}
......@@ -232,7 +167,7 @@
// backspace
if ( keyCode == 8 ) {
if ( keyCode === 8 ) {
event.preventDefault();
......@@ -251,7 +186,7 @@
// backspace
if ( keyCode == 8 ) {
if ( keyCode === 8 ) {
event.preventDefault();
......@@ -278,7 +213,7 @@
bevelThickness: bevelThickness,
bevelSize: bevelSize,
bevelEnabled: bevelEnabled,
bevelEnabled: true,
material: 0,
extrudeMaterial: 1
......@@ -288,49 +223,7 @@
textGeo.computeBoundingBox();
textGeo.computeVertexNormals();
// "fix" side normals by removing z-component of normals for side faces
// (this doesn't work well for beveled geometry as then we lose nice curvature around z-axis)
if ( ! bevelEnabled ) {
var triangleAreaHeuristics = 0.1 * ( height * size );
for ( var i = 0; i < textGeo.faces.length; i ++ ) {
var face = textGeo.faces[ i ];
if ( face.materialIndex == 1 ) {
for ( var j = 0; j < face.vertexNormals.length; j ++ ) {
face.vertexNormals[ j ].z = 0;
face.vertexNormals[ j ].normalize();
}
var va = textGeo.vertices[ face.a ];
var vb = textGeo.vertices[ face.b ];
var vc = textGeo.vertices[ face.c ];
var s = THREE.GeometryUtils.triangleArea( va, vb, vc );
if ( s > triangleAreaHeuristics ) {
for ( var j = 0; j < face.vertexNormals.length; j ++ ) {
face.vertexNormals[ j ].copy( face.normal );
}
}
}
}
}
var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
var centerOffset = - 0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
textMesh1 = new THREE.Mesh( textGeo, material );
......@@ -410,7 +303,7 @@
function onDocumentTouchStart( event ) {
if ( event.touches.length == 1 ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
......@@ -423,7 +316,7 @@
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册