UNPKG

vesh-vj

Version:

VESH's JavaScript Framework

373 lines (369 loc) 14.6 kB
;(function (V, W, $) { V.registScript(function (path, vm) { var _ = this, __ = {} { // 简历一个基础的3DObject对象,允许定义其position scale rotate move动画等等 V.inherit.apply(_, [W.Control, [path || "<div style='display:none;'></div>", V.getValue({ data: { type: 'plane', position: { x: 0, y: 0, z: 0 }, scale: { x: 1, y: 1, z: 1 }, rotate: { x: 0, y: 0, z: 0 }, width: 0, height: 0, deepth: 0, radius: 0, points: [], size: 'cover', color: { rgb: 0xffffff, opacity: 1.0 }, transparent: false, side: 0, style: 'basic', debug: false } }, vm)]]) _.is3D = true __.obj = null __.onLoad = _.onLoad __.render = _.render __.addControl = _.addControl __.removeControl = _.removeControl __.clearControl = _.clearControl __.dispose == _.dispose _.geometry = null _.material = null _.addDesc('three3D 对象') _.addDesc('属性:') _.addDesc('\ttype 类型mesh,line,cube,cylinder,sphere,plane') _.addDesc('\tposition {x,y,z}中心点方位') _.addDesc('\tscale 放大缩小') _.addDesc('\trotate 旋转') _.addDesc('\twidth 宽度适用于plane,cube,line') _.addDesc('\theight 高度适用plane,cube,cylinder') _.addDesc('\tdeepth 深度适用于cube,') _.addDesc('\tradius 半径适用于sphere,[top,bottom]两个半径适用于cylinder') _.addDesc('\tpoints 适用mesh,line') _.addDesc('\tfaces 适用mesh') _.addDesc('\tsize cover,repeat,mirror适用于image属性,') _.addDesc('\tcolor 颜色适用于全部,多个颜色适用于mesh与line') _.addDesc('\ttransparent 是否透明适用于全部') _.addDesc('\tside 适用于正反面0 正面 1 反面 2 正反面') _.addDesc('\tstyle 适用于basic,lambert,phong,line') _.addDesc('\tdebug:线框模式') _.addDesc('\tposition {x,y,z}中心点方位') _.addDesc('事件:') _.addDesc('\thover e hover:true/false') _.addDesc('\tclick e mousedown与mouseup在500ms之内时认为是click') _.addDesc('\tmousedown e D2Position,Position,D3Position') _.addDesc('\tmouseup e D2Position,Position,D3Position') _.addDesc('\tmousemove e D2Position,Position,D3Position') _.addDesc('\tvideoend 视频播放完成 一般是自动重播的') _.addDesc('定义:') _.addDesc("\tthreeobject: { path: '../../Scripts/ref/three.js;../../Scripts/ref/stats.min.js;../../Scripts/module/part/tobj.js;' }") } _.onLoad = function (node) { _.movie = (_.parent.vs[node.parent().attr('id')]) if (!_.movie.is3D) throw new Error('ThreeObject必须运行在ThreeMovie中') _.scene = _.movie.scene _.obj = null V.forC(_.events, function (k, v) { switch (k.toLowerCase()) { case 'hover': case 'click': case 'mousedown': case 'mouseup': case 'mousemove': case 'videoend': break default: _.bindEvent(_.node, k, v) break } }, function () { __.onLoad(node) }) } _.fill = function () { if (_.obj) return { EPosition: _.obj.position.clone(), ERotate: _.obj.rotation.clone(), EScale: _.obj.scale.clone() }; else return {}; } _.get2DPosition = function () { console.log(_.obj); if (_.obj && _.movie && _.obj.visible) { return _.movie.get2DPosition(_.obj); } else return {}; } _.createVideo = function (file, repeat, auto, loaded) { // 全局缓存视频 防止视频加载多次造成不同步 var _videos = window._videos = V.getValue(window._videos, {}) if (_videos[file]) { return _videos[file][0] } else { var filetype = (function () { switch (file.substr(file.lastIndexOf('.') + 1).toLowerCase()) { default: case 'mp4': return 'video/mp4' } })() var video = V.newEl('video', '', '').css('display', 'none').attr('autoplay', auto ? true : false).append('<source src="' + file + '" type="' + filetype + '">').appendTo(document.body) if (loaded) video[0].addEventListener('loadeddata', function () {loaded(video[0]);}) if (repeat) { video[0].addEventListener('ended', function () { _.call('videoend') video[0].play() }) } _videos[file] = video return _videos[file][0] } } if (_.video) _.video.remove() _.render = function (data) { V.forC(data, function (k, v) { switch (k.toLowerCase()) { case 'desc': _.desc() break case 'visible': if (_.obj) _.obj.visible = v ? true : false break case '2dposition': if (v && typeof (v) == 'function') { v.apply(_, [_.get2DPosition()]) } break case 'type': switch (v.toLowerCase()) { default: case 'mesh': case 'line': // 多面体 _.geometry = new THREE.Geometry() break case 'text': _.geometry = new THREE.TextGeometry(data.text, {}) break case 'plane': if (data.width && data.height) _.geometry = new THREE.PlaneGeometry(data.width, data.height) else V.showException('请输入width,height作为参数') break case 'cube': if (data.width && data.height && data.deepth) _.geometry = new THREE.CubeGeometry(data.width, data.height, data.deepth) else V.showException('请输入width,height,deepth作为参数') break case 'sphere': if (data.radius) { _.geometry = new THREE.SphereGeometry(data.radius, 32, 32) } else V.showException('请输入radius作为半径参数') break case 'cylinder': if (data.radius) { if (V.isArray(data.radius)) _.geometry = new THREE.CylinderGeometry(data.radius[0], data.radius[1], data.height, 32, 32) else _.geometry = new THREE.CylinderGeometry(data.radius, data.radius, data.height, 32, 8) } else V.showException('请输入radius作为半径参数') break } if (data.points && data.points.length > 0) { V.each(data.points, function (v2) { _.geometry.vertices.push(new THREE.Vector3(v2.x, v2.y, v2.z)) }, null, true) } if (data.faces && data.faces.length > 0) { V.each(data.faces, function (v2) { if (v2.length == 3) _.geometry.faces.push(new THREE.Face3(v2[0], v2[1], v2[2])) else if (v2.length > 3) _.geometry.faces.push(new THREE.Face4(v2[0], v2[1], v2[2], v2[3])) else V.showException('faces 不支持少于3点的面:' + v2.length) }, null, true) } if (data.color && V.isArray(data.color) && data.color.length > 1) { V.each(data.color, function (v2) { _.geometry.colors.push(new THREE.Color(v2.rgb, v2.opacity)) }, null, true) } break case 'style': __.data2 = { side: (function () { switch (data.side) { default: case 0: return THREE.FrontSide case 1: return THREE.BackSide case 2: return THREE.DoubleSide } })(), transparent: data.transparent, needUpdate: true, color: (data.color && !V.isArray(data.color)) ? data.color.rgb : 0, opacity: (data.color && !V.isArray(data.color)) ? data.color.opacity : 1, perPixel: true, debug: data.debug } if (__.data2.debug) { __.data2.wireframe = true; __.data2.wireframeLinecap = 'round'; __.data2.wireframeLinewidth = 2; } delete data.side delete data.transparent delete data.needUpdate delete data.debug switch (v.toLowerCase()) { default: case 'basic': _.material = new THREE.MeshBasicMaterial(__.data2) break case 'lambert': // ambient,emissive 两个可见与不可见光源 _.material = new THREE.MeshLambertMaterial(__.data2) break case 'phong': __.data2 = V.merge({ shininess: 30, specular: __.data2.color }, __.data2) _.material = new THREE.MeshPhongMaterial(__.data2) break case 'line': __.data2.vertexColors = true __.data2.linewidth = V.getValue(data.width, 1) _.material = new THREE.LineBasicMaterial(__.data2) break } break case 'vedio': _.map = null var wrap = (function () { switch (data.size.toLowerCase()) { default: case 'cover': return THREE.ClampToEdgeWrapping case 'repeat': return THREE.RepeatWrapping case 'mirror': return THREE.MirroredRepeatWrapping } })() if (v && V.isArray(v) && v.length > 1) { var textures = [] var data2 = V.merge({}, __.data2) var vedios = [] V.each(v, function (v2) { var video = _.createVideo(v2, true, false, function (vedio2) { vedios.push(vedio2) if (vedios.length == v.length) { V.each(vedios, function (v3) {v3.play();}, null,true); } }) var map = new THREE.VideoTexture(video) map.wrapS = map.wrapT = wrap var mesh = new THREE.MeshBasicMaterial({ color: data2.color, opacity: data2.opacity, map: map, side: data2.side }) textures.push(mesh) }, function () { _.material = new THREE.MeshFaceMaterial(textures) }, true) } else { _.video = _.createVideo(v, true,true); _.map = new THREE.VideoTexture(_.video) _.map.wrapS = _.map.wrapT = wrap } break case 'image': _.map = null var wrap = (function () { switch (data.size.toLowerCase()) { default: case 'cover': return THREE.ClampToEdgeWrapping case 'repeat': return THREE.RepeatWrapping case 'mirror': return THREE.MirroredRepeatWrapping } })() if (v && V.isArray(v) && v.length > 1) { var textures = [] var data2 = V.merge({}, __.data2) V.each(v, function (v2) { // var map = THREE.ImageUtils.loadTexture(v2) var map = new THREE.TextureLoader().load(v2) map.wrapS = map.wrapT = wrap var mesh = new THREE.MeshBasicMaterial({ color: data2.color, opacity: data2.opacity, map: map, side: data2.side }) textures.push(mesh) }, function () { _.material = new THREE.MeshFaceMaterial(textures) }, true) } else { _.map = new THREE.TextureLoader().load(v) _.map.wrapS = _.map.wrapT = wrap } break } }, function () { if (data.type) { if (_.map) _.material.map = _.map; // 对材质的设置必须在生成Mesh之前否则就是更新Mesh.Material也无济于事,可能是更新的属性不对导致的或者其属性是clone的 switch (data.type.toLowerCase()) { default: case 'sphere': case 'cylinder': case 'plane': case 'mesh': case 'cube': case 'text': _.obj = new THREE.Mesh(_.geometry, _.material) break case 'line': _.obj = new THREE.Line(_.geometry, _.material, THREE.LinePieces) break } _.movie.add3DObject(_) } if (_.obj) V.forC(data, function (k2, v2) { switch (k2.toLowerCase()) { case 'position': V.merge(_.obj.position, v2, true) break case 'rotate': V.forC(v2, function (k3, v3) { _.obj.rotation[k3] = v3 * Math.PI / 180 }, null, true) break case 'scale': V.merge(_.obj.scale, v2, true) break case 'play': if (v2 && typeof (v2) == 'function') { var id = '' var func = v2 var go = function () { if (_.stats) _.stats.update() if (_.vm.get().play) { id = window.requestAnimationFrame(go) } else { __.resumego = go window.cancelAnimationFrame(id) } func.apply(_.movie.vms, [_.vm.data, _.vm]) // _.movie.redraw() } go() } else if (true === v2 && __.resumego) { __.resumego() } break } }, _.movie.redraw,true); },true); } _.dispose = function () { V.tryC(function () { _.call('dispose'); if (_.obj) { _.movie.scene.remove(_.obj); _.movie.redraw(); } }); _.node.remove() } // 动态添加控件到指定位置 如果不指定那么会添加到最后 _.addControl = function () { V.showException('tobj 不允许addControl') } _.removeControl = function () { V.showException('tobj 不允许removeControl') } _.clearControl = function () { V.showException('tobj 不允许clearControl') } }) })(VJ, VJ.view, jQuery)