overlay1.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. var initOverlay = function(THREE){
  2. var _planeGeometry = new THREE.PlaneGeometry(settings.overlay.width, settings.overlay.height,1,1)
  3. var _boxGeometry = new THREE.BoxBufferGeometry(settings.overlay.width, settings.overlay.height, settings.overlay.depth )
  4. //ie的mesh 加了polygonOffset也是会重叠。所以去掉前面的face: (但是突然ie又播放不了videoTexture)
  5. var newIndex = [..._boxGeometry.index.array]
  6. newIndex.splice(4*6,6)
  7. _boxGeometry.setIndex(new THREE.BufferAttribute(new Uint16Array(newIndex), 1))
  8. var _boxMat = new THREE.MeshBasicMaterial({//MeshStandardMaterial
  9. color:"#eeeeee",
  10. transparent: !0 ,
  11. opacity:0.8
  12. })
  13. var overlayGroup = new THREE.Object3D; player.model.add(overlayGroup); overlayGroup.name = "overlayGroup"
  14. player.overlayGroup = overlayGroup;
  15. var Overlay = function(info){
  16. THREE.Object3D.call(this);
  17. this.sid = info.sid;
  18. if(info.media)this.preDeal(info)
  19. this.build(info);
  20. this.name = "overlay_"+this.sid;
  21. }
  22. Overlay.prototype = Object.create(THREE.Object3D.prototype);
  23. Overlay.prototype.build = function(info){
  24. if( info.media.includes('text') && !info.words)return;
  25. var plane = new THREE.Mesh(_planeGeometry, new THREE.MeshBasicMaterial({//MeshStandardMaterial
  26. color:"#00c8af",
  27. opacity:0.4,
  28. transparent: !0,
  29. polygonOffset : true,//是否开启多边形偏移 //ie不开启时blank也不会闪烁
  30. polygonOffsetFactor : -0.9,//多边形偏移因子
  31. polygonOffsetUnits : -4.0,//多边形偏移单位
  32. }) )
  33. plane.renderOrder = 3
  34. this.add(plane);
  35. this.plane = plane;
  36. if(info.hasBox){
  37. this.addBox(true)
  38. }
  39. overlayGroup.add(this);
  40. if(info.media){
  41. if(info.media.includes('video')){
  42. var video = $('<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>')[0]
  43. video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
  44. $(video).on('contextmenu', function () { return false; });//禁止右键点击出
  45. video.src = manage.dealURL(info.file) ;
  46. info.media = video;
  47. info.type = "video"
  48. video.addEventListener('loadeddata', ()=>{
  49. console.log(this.sid + " loaded!!!")
  50. })
  51. video.volume = 0
  52. video.muted = true
  53. }else if(info.media.includes('photo')){
  54. /* var img = new Image();
  55. img.src = manage.dealURL(info.file) //"https://4dkk.4dage.com/images/images"+Config.projectNum+"/overlay"+this.sid+".jpg?m="+new Date().getTime()
  56. info.media = img
  57. */
  58. info.type = "photo"
  59. }else if(info.media.includes('text')){
  60. info.type = "text";
  61. var fontSize = 40;
  62. var lineHeight = fontSize * 2.1;//fontSize + 行间距
  63. var texWidthRitio = 0.86
  64. var canvas = document.createElement('canvas');
  65. var context = canvas.getContext('2d');
  66. canvas.width = 1024;
  67. context.font = `${fontSize}px 微软雅黑`;
  68. var result = []
  69. info.words.forEach((words)=>{
  70. if(!words){result.push("");return;}
  71. result = result.concat ( breakLinesForCanvas(
  72. words,
  73. //'使用很寻常的二分查找,如果某一个位置之前的文字宽度小于等于设定的宽度,并且它之后一个字之前的文字宽度大于设定的宽度,那么这个位置就是文本的换行点。上面只是找到一个换行点,对于输入的一段文本,需要循环查找,直到不存在这样的换行点为止, 完整的代码如下',
  74. context, canvas.width * texWidthRitio ) )
  75. })
  76. canvas.height = (result.length + 1 ) * lineHeight
  77. var context = canvas.getContext('2d');//不知为什么要再获取一次context才行
  78. context.font = `${fontSize}px 微软雅黑`;
  79. /* context.fillStyle = '#fff';
  80. context.fillRect(0,0,canvas.width,canvas.height); */
  81. context.fillStyle = '#f5c772';
  82. result.forEach(function(line, index) {
  83. context.fillText(line, canvas.width * (1-texWidthRitio)/ 2, lineHeight * (index + 1));
  84. });
  85. var url = canvas.toDataURL()
  86. var img = new Image();
  87. img.src = url;
  88. info.media = img;
  89. info.lineCount = result.length
  90. }
  91. plane.material.opacity = 1;
  92. plane.material.color = new THREE.Color(1,1,1)
  93. }
  94. if(info.width == void 0) info.width = settings.overlay.width;
  95. if(info.height == void 0) info.height = settings.overlay.height;
  96. this.setFromInfo(info)
  97. }
  98. Overlay.prototype.computeMapRepeat = function(info){//使得文字不变形
  99. clearInterval(this.mapInterval);
  100. var map = this.plane.material.map;
  101. var tw = map.image.width, th = map.image.height,
  102. w = this.width, h = this.height;
  103. var ratio = (h / w) / (th / tw); //显示的部分占据整个图高度的比例
  104. map.repeat.y = ratio
  105. if(th / tw > h / w){
  106. //如果贴图设置成不repeat(缺点是会有一段白屏期)
  107. /* map.offset.y = 1 - ratio;//向下移动 1-ratio个高度, 使图片的顶部显示在plane的最上方;之后滚动时正常repeat在 1-ratio到0之间变化 , 为了连续变化,改成 1 到 -ratio
  108. this.mapInterval = setInterval(()=>{
  109. map.offset.y -= 0.003;
  110. if(map.offset.y < -ratio )map.offset.y = 1
  111. },20) */
  112. //如果贴图设置成 repeat(缺点是 可能衔接时的缝隙比较窄)
  113. map.wrapS = map.wrapT = THREE.RepeatWrapping;
  114. map.offset.y = 1 - ratio;//向下移动 1-ratio个高度, 使图片的顶部显示在plane的最上方;之后滚动时正常repeat在 1-ratio到0之间变化 , 为了连续变化,改成 1 到 -ratio
  115. this.mapInterval = setInterval(()=>{
  116. map.offset.y -= 0.013 / info.lineCount ;
  117. //if(map.offset.y < -ratio )map.offset.y = 1
  118. },20)
  119. }else{//如果图可以完全展示
  120. map.offset.y = (1 - ratio) / 2;//居中
  121. map.wrapS = map.wrapT = THREE.ClampToEdgeWrapping;
  122. }
  123. map.needsUpdate = true;
  124. }
  125. Overlay.prototype.setFromInfo = function(info){//1 恢复到编辑之前 2 初始加载
  126. var plane = this.plane;
  127. info.width && (this.scale.setX(info.width/settings.overlay.width),this.width = info.width)
  128. info.height && (this.scale.setY(info.height/settings.overlay.height),this.height = info.height)
  129. info.depth && this.scale.setZ(info.depth/settings.overlay.depth)
  130. info.pos && this.position.copy(info.pos);
  131. info.qua && this.quaternion.copy(info.qua);
  132. if(info.type){
  133. if(!plane.material.map){
  134. if(info.type == "video"){
  135. plane.material.map = new THREE.VideoTexture( info.media );
  136. }else if(info.type == "photo"){
  137. plane.material.map = Texture.load(info.file,()=>{
  138. if(this._loadDone)this._loadDone()
  139. })
  140. }else{
  141. plane.material.map = new THREE.Texture;
  142. plane.material.map.image = info.media;
  143. info.media.onload = ()=>{
  144. plane.material.map.needsUpdate = true
  145. this.computeMapRepeat(info)
  146. }
  147. }
  148. plane.material.map.wrapS = plane.material.map.wrapT = THREE.ClampToEdgeWrapping;
  149. plane.material.map.minFilter = THREE.LinearFilter;
  150. plane.material.map.magFilter = THREE.LinearFilter;
  151. plane.material.map.generateMipmaps = true;
  152. }else plane.material.map.image = info.media;
  153. this.file = info.file;
  154. }
  155. this.overlayType = info.type;
  156. if(!!this.hasBox != !!info.hasBox){
  157. this.addBox(!this.hasBox);
  158. }
  159. }
  160. Overlay.prototype.addBox = function(state){
  161. if(state == !!this.hasBox){
  162. return;
  163. }
  164. if(state){
  165. var box = new THREE.Mesh(_boxGeometry , _boxMat)
  166. box.position.set(0,0,settings.overlay.depth/2);
  167. box.renderOrder = 3
  168. this.plane.position.set(0,0,settings.overlay.depth );
  169. this.add(box);
  170. this.box = box;
  171. }else{
  172. this.plane.position.set(0,0,0);
  173. this.remove(this.box);
  174. this.box = null;
  175. }
  176. this.hasBox = state
  177. }
  178. Overlay.prototype.preDeal = function(info){
  179. info.pos = new THREE.Vector3().fromArray(info.pos)
  180. info.qua = new THREE.Quaternion().fromArray(info.qua)
  181. info.width = parseFloat(info.width)
  182. info.height = parseFloat(info.height)
  183. info.depth = parseFloat(info.depth)
  184. info.hasBox = parseInt(info.hasBox)
  185. info.pos.x = parseFloat(info.pos.x)
  186. info.pos.y = parseFloat(info.pos.y)
  187. info.pos.z = parseFloat(info.pos.z)
  188. info.qua.x = parseFloat(info.qua.x)
  189. info.qua.y = parseFloat(info.qua.y)
  190. info.qua.z = parseFloat(info.qua.z)
  191. info.qua.w = parseFloat(info.qua.w)
  192. if(info.media.includes("text")){
  193. /*
  194. 只有http能加载
  195. */
  196. $.ajax({
  197. url: "/api/web/list",
  198. type: 'POST',
  199. dataType: "json",
  200. cache: false,
  201. contentType: 'application/json;charset=UTF-8',
  202. data : JSON.stringify({"pageNum":1,"pageSize":1000} ),
  203. success: (data)=>{
  204. console.log(data)
  205. var words = [];
  206. data.data.list.forEach((item,index)=>{
  207. /* words += item.nickName; words += " "
  208. words += item.createTime; words += "\n\n"
  209. words += item.msg; words += "\n"
  210. words += "————————\n\n" */
  211. words.push(item.nickName + " " + item.createTime);
  212. //words.push("");
  213. words.push(item.msg);
  214. words.push("————————————————");
  215. words.push("");
  216. })
  217. console.log(words)
  218. info.words = words
  219. this.build(info)
  220. },
  221. error: function (msg) {
  222. console.log(msg)
  223. }
  224. });
  225. }
  226. }
  227. function findBreakPoint(text, width, context) {
  228. var min = 0;
  229. var max = text.length - 1;
  230. while (min <= max) {
  231. var middle = Math.floor((min + max) / 2);
  232. var middleWidth = context.measureText(text.substr(0, middle)).width;
  233. var oneCharWiderThanMiddleWidth = context.measureText(text.substr(0, middle + 1)).width;
  234. if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
  235. return middle;
  236. }
  237. if (middleWidth < width) {
  238. min = middle + 1;
  239. } else {
  240. max = middle - 1;
  241. }
  242. }
  243. return -1;
  244. }
  245. function breakLinesForCanvas(text, context, width, font) {
  246. var result = [];
  247. var breakPoint = 0;
  248. if (font) {
  249. context.font = font;
  250. }
  251. while ((breakPoint = findBreakPoint(text, width, context)) !== -1) {
  252. result.push(text.substr(0, breakPoint));
  253. text = text.substr(breakPoint);
  254. }
  255. if (text) {
  256. result.push(text);
  257. }
  258. return result;
  259. }
  260. window.Overlay = Overlay;
  261. }