【问题标题】:Angular or Three.js not pulling image from server, but rather browser cacheAngular 或 Three.js 不是从服务器中提取图像,而是浏览器缓存
【发布时间】:2015-09-23 22:20:41
【问题描述】:

请参阅本文末尾的更新 3,了解最近的活动/plunker

我在 Node/Express 应用程序之上使用 AngularJS。在这个应用程序中,我使用 three.js 来显示一个 3D 对象。包裹这个对象的纹理会改变,但文件名不会改变(例如,纹理图像的颜色会改变,但文件名仍然是 Texture_0.png)。

纹理文件存储在 Azure Blob 存储中,并且我启用了 CORS,因此它可以正确显示。如果我在新会话中更新图像并将其上传到 Azure Blob 存储,则在我第一次渲染 3D 对象时,它会显示纹理及其更改。但是,每当我上传新更改并尝试重新渲染时,它都会显示浏览器缓存的图像,而不是服务器中存储和引用的新图像。需要刷新页面才能看到更改,但我需要在单击弹出模式的按钮后显示此内容,而不是页面刷新。

如何在不刷新页面的情况下让 AngularJS 显示纹理图像的服务器版本而不是浏览器缓存?

我尝试添加一些随机数学来强制浏览器从服务器下载,但它不起作用。相关代码如下:

Three.JS 3D 对象代码:

$scope.generate3D = function () {

// 3D OBJECT - Variables
var texture0 = baseBlobURL + 'Texture_0.png?' + Math.random();
var boxDAE = baseBlobURL + 'Box.dae?' + Math.random();
var scene;
var camera;
var renderer;
var box;
var controls;
var newtexture;


// 3D OBJECT - Generate  

newtexture = THREE.ImageUtils.loadTexture(texture0);

//Instantiate a Collada loader
var loader = new THREE.ColladaLoader();

loader.options.convertUpAxis = true;
loader.load(boxDAE, function (collada) {

box = collada.scene;

box.traverse(function (child) {

if (child instanceof THREE.SkinnedMesh) {

var animation = new THREE.Animation(child, child.geometry.animation);
animation.play();

}
});

box.scale.x = box.scale.y = box.scale.z = .2;
box.updateMatrix();

init();
animate();
});

function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();

renderer.setClearColor(0xdddddd);

renderer.setSize(500, 500);

// Load the box file
scene.add(box);

// Lighting
var light = new THREE.AmbientLight();
scene.add(light);

// Camera
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;

camera.lookAt(scene.position);

// Rotation Controls
controls = new THREE.OrbitControls(camera, renderer.domElement);

controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;

controls.noZoom = false;
controls.noPan = false;

var myEl = angular.element(document.querySelector('#webGL-container'));
myEl.append(renderer.domElement);

}

function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);               
}
}

在模态中调用 3D 对象和弹出的 Angular 函数:

$scope.boxPreview = function () {
$scope.generate3D();
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: 'lg'
}

作为脚本标签嵌入的模态(我需要在视图中使用它,因为图像 URL 是唯一的,并且运行我的视图的代码需要这些变量以及 3D 对象代码):

<script type="text/ng-template" id="myModalContent.html">
    <div class="modal-header">
        <h3 class="modal-title">Box Preview</h3>
    </div>
    <div class="modal-body">

        <div id="webGL-container" width="500px">
        </div>

    </div>
    <div class="modal-footer">
        <button class="btn btn-primary" data-ng-click="ok()">Close</button>
    </div>
</script>

更新 1:

在 Chrome 中查看网络选项卡时,我可以看到它正在拉下正确的图像,但只是没有在 Modal 中显示。我尝试禁用缓存,但这没有效果。这就像 three.js 将图像保存在某个地方......但我只是不知道如何清除它。

更新 2:

使用来自 Mr.doob listed in this post 的建议,在出现以下错误之前,我可以在不刷新页面的情况下重新加载它:

RangeError: 超出最大调用堆栈大小

当我将以下代码添加到我实例化加载程序的位置时:

THREE.ImageLoader.prototype._load = THREE.ImageLoader.prototype.load;
THREE.ImageLoader.prototype.load = function (url, onLoad, onProgress, onError) {
this._load(url + '?' + Math.random(), onLoad, onProgress, onError);
};

//Instantiate a Collada loader
var loader = new THREE.ColladaLoader();

这是事件的顺序:

1) 在第一次单击以在新会话中显示 3D 框时,会显示更改

2) 更改纹理并上传,然后在同一会话中单击显示 3D 框,它会显示更改。以前,它在页面刷新之前不会显示。

3) 更改纹理并上传,然后单击以在同一会话中显示 3D 框。 RangeError: 超出最大调用堆栈大小

明确地说,我在模态中打开它。并且已经看到 Modals 产生这些错误的问题,除了我在路由级别只保留一个控制器调用。

更新 3:

我整理了以下内容:

http://plnkr.co/edit/DGZA9LUBZWsLWrmXaaKD

它正在使用我的 Dropbox 公用文件夹来获取图像。我遇到了同样的问题,如果我覆盖纹理文件,当我选择框预览时它不会更新,除非我刷新页面。我需要这个来刷新点击时的盒子纹理。一些重要说明:

1) 我在控制台记录了术语“已加载”,以表明即使在模态关闭后它仍会继续呈现。我不确定是否需要连续渲染/动画,因为我只需要使用 OrbitControls 旋转盒子。请让我知道是否有更好的方法或者这是否导致缓存问题/我们需要销毁场景/重新创建它以更新框

2)使用Mr.Doob推荐的代码,我可以更新服务器上的图像并让它重新正确渲染一次,然后它给我一个错误:

未捕获的 RangeError:超出最大调用堆栈大小

代码如下:

THREE.ImageLoader.prototype._load = THREE.ImageLoader.prototype.load;
            THREE.ImageLoader.prototype.load = function (url, onLoad, onProgress, onError) {
               this._load(url + '?' + Math.random(), onLoad, onProgress, onError);
           };

我已将这段代码留在原处,因为它在崩溃之前至少实现了我想要的一次。

3) 由于我们使用的是公共保管箱,我不确定那些协助我的人是否能够用更改覆盖 Texture_0.png 文件(我在油漆中打开它,只是涉足了一些东西并重新上传到dropbox),但您可以将 URL 更改为您自己的 dropbox 以进行测试,因为您可以上传并看到该框纹理不会刷新,除非您重新加载网页 (plunker)。

【问题讨论】:

  • 第三方dom相关代码属于一个指令
  • 关于如何将其放入指令的任何指导?这会解决浏览器缓存问题吗?它有点棘手,因为此页面上的代码从 routeparams 获取传递给它的变量以确定图像的 URL 路径。有没有非指令选项?
  • 可以在指令中注入$routeParams。切换代码并不难。我没有看到该 dom 元素如何与代码相关联。虽然每次打开模式时都会是新实例。
  • 我的页面也需要匹配的路由参数,所以这就是我犹豫是否要拆分它的原因。我已经看到很多关于制定指令/许多方法的参考资料。你有任何你认为符合我需要的链接吗?
  • 指令公开了它绑定的实际元素。可以从中访问应用程序的任何其他部分,如果范围未隔离,则继承父控制器范围。还可以访问任何服务。如果您可以注入控制器,则可以注入指令。很容易找到关于如何在指令中集成 3rd 方代码的文章

标签: javascript angularjs azure three.js browser-cache


【解决方案1】:

如果你是在后面编辑three.js的图片文件而不改变文件名,并且你想刷新材质纹理,你可以使用这样的模式:

mesh.material.map.dispose(); // unrelated, but important!
mesh.material.map = THREE.ImageUtils.loadTexture( "filename.jpg" + "?" + Math.random() );

如果没有动画循环,则需要强制重新渲染,如下所示:

mesh.material.map.dispose(); // unrelated, but important!
mesh.material.map = THREE.ImageUtils.loadTexture( "filename.jpg" + "?" + Math.random(), undefined, render );

three.js r.72

【讨论】:

  • 在我当前的 three.js 代码中,我没有定义网格。我如何将它与我的代码结合起来?
  • 我的纹理会是一种材质吗? Collada loader 加载的 Collada 文件引用 .png 文件
  • 我可以回答有关three.js 的问题,但我无法帮助您编写代码。也许您需要创建一个简单的实例来演示该问题。
  • 纹理不是“材质”,并且 Collada 加载器不“使用”网格。加载器返回对象的层次结构,其中一些可以是THREE.Mesh
  • 您的ImageLoader.load() hack 是递归的。难怪。尝试将以下行添加到ImageLoader.load()url = url + '?' + Math.random();
【解决方案2】:

@weslangley 的回答对于大部分three.js 用户来说在技术上是正确的,因为他们使用材料。在我非常独特的情况下,我有一个独特的 Collada 文件,我必须在其中编辑 ImageLoader.js 文件,以便让它从服务器即时返回具有相同文件名(但图像内容不同)的图像文件。 我不建议接触源代码,但在我的情况下,我在 ImageLoader.js 的加载函数下添加了以下行:

url = url + '?' + Math.random();

对我来说这很有效,但同样,对于 99.9% 的 three.js 其他用户来说,这可能不适用。

【讨论】:

    猜你喜欢
    • 2013-01-09
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 2017-09-04
    相关资源
    最近更新 更多