当前位置: 首页 > 知识库问答 >
问题:

三js-uvsNeedUpdate=True不触发更新

奚光霁
2023-03-14

我正在做一个三点的。js场景,加载5个网格,每个网格具有包含单个图像纹理的单个材质。加载这些图像后,我将尝试完成以下任务:

  1. 加载20幅高分辨率图像
  2. 更新每个网格的材质属性,以将5种材质(每个材质具有1种图像纹理)的数组加载到每个网格中
  3. 更新每个网格几何体的FaceVertexUV,以指向新纹理中的适当偏移

几何上的留档对于Geometry.faceVertex Uvs几乎没有什么要说的,但是这篇SO帖子建议人们在使用faceVertex Uvs时可以使用以下方法来处理几何中的多种材料:

geometry.faceVertexUvs[ materialIndex ][ faceIndex ][ vertexIndex ]

问题是,在完成上述步骤后,我调用mesh[meshIdx]。几何学uvsNeedUpdate=true 但我的新材质不会出现,我的网格保持不变。有人知道为什么会这样吗?

我将非常感谢其他人在这个问题上提供的任何建议或见解!

这是我的完整代码示例

/**
* Globals
**/

// Create a store for all images contained in the visualization
var imageList = null;

// Create a store for the image atlas files. Each key will represent
// the index position of the atlas file, and the value will point
// to the material at that index position
var materials = {32: {}, 64: {}};

// Create global configs for image and atlas sizing
var image, atlas;

// Create a store of meshes
var meshes = [];

/**
* Create Scene
**/

// Create the scene and a camera to view it
var scene = new THREE.Scene();

/**
* Camera
**/

// Specify the portion of the scene visiable at any time (in degrees)
var fieldOfView = 75;

// Specify the camera's aspect ratio
var aspectRatio = window.innerWidth / window.innerHeight;

/*
Specify the near and far clipping planes. Only objects
between those planes will be rendered in the scene
(these values help control the number of items rendered
at any given time)
*/
var nearPlane = 100;
var farPlane = 50000;

// Use the values specified above to create a camera
var camera = new THREE.PerspectiveCamera(
  fieldOfView, aspectRatio, nearPlane, farPlane
);

// Finally, set the camera's position
camera.position.z = 12000;
camera.position.y = -2000;

/**
* Renderer
**/

// Create the canvas with a renderer
var renderer = new THREE.WebGLRenderer({ antialias: true });

// Add support for retina displays
renderer.setPixelRatio( window.devicePixelRatio );

// Specify the size of the canvas
renderer.setSize( window.innerWidth, window.innerHeight );

// Add the canvas to the DOM
document.body.appendChild( renderer.domElement );

/**
* Load External Data
**/

// Identify data endpoint
var dataUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/data/';

// Create a store for image position information
var imagePositions = null;

// Load the image position JSON file
var fileLoader = new THREE.FileLoader();
fileLoader.load(dataUrl + 'image_tsne_projections.json', function(data) {
  imagePositions = JSON.parse(data);
  conditionallyBuildGeometries(32)
})

/**
* Load Atlas Textures
**/

// List of all textures to be loaded, the size of subimages
// in each, and the total number of atlas files for each size
var textureSets = {
  32: { size: 32, count: 5 },
  64: { size: 64, count: 20 }
}

// Create a texture loader so we can load our image files
var textureLoader = new THREE.TextureLoader();

function loadTextures(size) {
  for (var i=0; i<textureSets[size].count; i++) {
    var url = dataUrl + 'atlas_files/' + size + 'px/atlas-' + i + '.jpg';
    textureLoader.load(url, handleTexture.bind(null, size, i));
  }
}

// Callback function that adds the texture to the list of textures
// and calls the geometry builder if all textures have loaded 
function handleTexture(size, idx, texture) {
  var material = new THREE.MeshBasicMaterial({ map: texture });
  materials[size][idx] = material;
  conditionallyBuildGeometries(size, idx)
}

// If the textures and the mapping from image idx to positional information
// are all loaded, create the geometries
function conditionallyBuildGeometries(size, idx) {
  if (size === 32) {
    var nLoaded = Object.keys(materials[size]).length;
    var nRequired = textureSets[size].count;
    if (nLoaded === nRequired && imagePositions) {  
      document.querySelector('#loading').style.display = 'none';
      buildGeometry(size);
      loadTextures(64)
    }
  } else {
    updateGeometry(size, idx)
  }
}

loadTextures(32)

/**
* Build Image Geometry
**/

// Iterate over the textures in the current texture set
// and for each, add a new mesh to the scene
function buildGeometry(size) {
  setImageAndAtlasSize(size);
  for (var i=0; i<textureSets[size].count; i++) {
    // Create one new geometry per atlas
    var geometry = new THREE.Geometry();
    for (var j=0; j<atlas.cols*atlas.rows; j++) {
      geometry = updateVertices(geometry, i, j);
      geometry = updateFaces(geometry);
      geometry = updateFaceVertexUvs(geometry, j, 0);
    }
    buildMesh(geometry, materials[size][i]);
  }
}

function setImageAndAtlasSize(size) {
  // Identify the subimage size in px (width/height) and the
  // size of the image as it will be displayed in the map
  image = { width: size,  height: size, shownWidth: 64, shownHeight: 64 };
  
  // Identify the total number of cols & rows in the image atlas
  atlas = { width: 2048, height: 2048, cols: 2048/size, rows: 2048/size };
}

// Get the x, y, z coords for the subimage at index position j
// of atlas in index position i
function getCoords(i, j) {
  var idx = (i * atlas.rows * atlas.cols) + j;
  var coords = imagePositions[idx];
  coords.x *= 2200;
  coords.y *= 1200;
  coords.z = (-200 + j/100);
  return coords;
}

// Add one vertex for each corner of the image, using the 
// following order: lower left, lower right, upper right, upper left
function updateVertices(geometry, i, j) {
  // Retrieve the x, y, z coords for this subimage
  var coords = getCoords(i, j);
  geometry.vertices.push(
    new THREE.Vector3(
      coords.x,
      coords.y,
      coords.z
    ),
    new THREE.Vector3(
      coords.x + image.shownWidth,
      coords.y,
      coords.z
    ),
    new THREE.Vector3(
      coords.x + image.shownWidth,
      coords.y + image.shownHeight,
      coords.z
    ),
    new THREE.Vector3(
      coords.x,
      coords.y + image.shownHeight,
      coords.z
    )
  );
  return geometry;
}

// Create two new faces for a given subimage, then add those
// faces to the geometry
function updateFaces(geometry) {
  // Add the first face (the lower-right triangle)
  var faceOne = new THREE.Face3(
    geometry.vertices.length-4,
    geometry.vertices.length-3,
    geometry.vertices.length-2
  )
  // Add the second face (the upper-left triangle)
  var faceTwo = new THREE.Face3(
    geometry.vertices.length-4,
    geometry.vertices.length-2,
    geometry.vertices.length-1
  )
  // Add those faces to the geometry
  geometry.faces.push(faceOne, faceTwo);
  return geometry;
}

function updateFaceVertexUvs(geometry, j, materialIdx) {  
  // Identify the relative width and height of the subimages
  // within the image atlas
  var relativeW = image.width / atlas.width;
  var relativeH = image.height / atlas.height;

  // Identify this subimage's offset in the x dimension
  // An xOffset of 0 means the subimage starts flush with
  // the left-hand edge of the atlas
  var xOffset = (j % atlas.cols) * relativeW;
  
  // Identify this subimage's offset in the y dimension
  // A yOffset of 0 means the subimage starts flush with
  // the bottom edge of the atlas
  var yOffset = 1 - (Math.floor(j/atlas.cols) * relativeH) - relativeH;
  
  // Create an empty list of faceVertexUvs for the given material Idx
  // if it doesn't exist yet
  if (!geometry.faceVertexUvs[materialIdx]) {
    geometry.faceVertexUvs[materialIdx] = [];
  }

  // Use the xOffset and yOffset (and the knowledge that
  // each row and column contains only 32 images) to specify
  // the regions of the current image
  geometry.faceVertexUvs[materialIdx][j*2] = [
    new THREE.Vector2(xOffset, yOffset),
    new THREE.Vector2(xOffset + relativeW, yOffset),
    new THREE.Vector2(xOffset + relativeW, yOffset + relativeH)
  ];

  // Map the region of the image described by the lower-left, 
  // upper-right, and upper-left vertices to `faceTwo`
  geometry.faceVertexUvs[materialIdx][(j*2) + 1] = [
    new THREE.Vector2(xOffset, yOffset),
    new THREE.Vector2(xOffset + relativeW, yOffset + relativeH),
    new THREE.Vector2(xOffset, yOffset + relativeH)
  ];

  return geometry;
}

function buildMesh(geometry, material) {
  // Convert the geometry to a BuferGeometry for additional performance
  //var geometry = new THREE.BufferGeometry().fromGeometry(geometry);
  // Combine the image geometry and material into a mesh
  var mesh = new THREE.Mesh(geometry, [material]);
  // Set the position of the image mesh in the x,y,z dimensions
  mesh.position.set(0,0,0)
  // Add the image to the scene
  scene.add(mesh);
  // Save this mesh
  meshes.push(mesh);
}

/**
* Update Geometries with new VertexUvs and materials
**/

function updateGeometry(size, idx) {

  // Update the image and atlas sizes
  setImageAndAtlasSize(size)

  // Determine how many of the higher resolution atlas files
  // it takes to account for all subimages in a lower resolution
  // atlas file
  var lowResPerAtlas = (2048/32)**2;
  var highResPerAtlas = (2048/64)**2;
  var atlasRatio = lowResPerAtlas / highResPerAtlas;

  // Determine which of the original meshes the newly-loaded high-res
  // atlas corresponds to
  var meshIdx = Math.floor(idx/atlasRatio);
  
  // Determine the material index position to use in this mesh.
  // The mesh's materials array will look like this:
  // mesh.material = [32px, 64px_0, 64px_1, 64px_2, 64px_3, 64_px_4];
  var materialIdx = (idx % atlasRatio) + 1;

  // Add the newly loaded material into the appropriate mesh
  meshes[meshIdx].material[materialIdx] = materials[size][idx];

  //console.log(meshIdx, materialIdx, idx, meshes[materialIdx].material)

  // Pluck out the geometry of this mesh update:
  var geometry = meshes[meshIdx].geometry;

  for (var j=0; j<highResPerAtlas; j++) {
    geometry = updateFaceVertexUvs(geometry, j, materialIdx);
  }
  
  geometry.faceVertexUvs[0] = [];

  meshes[meshIdx].geometry = geometry;
  meshes[meshIdx].geometry.colorsNeedUpdate = true;
  meshes[meshIdx].geometry.groupsNeedUpdate = true;
  meshes[meshIdx].geometry.lineDistancesNeedUpdate = true;
  meshes[meshIdx].geometry.normalsNeedUpdate = true;
  meshes[meshIdx].geometry.uvsNeedUpdate = true;
  meshes[meshIdx].geometry.verticesNeedUpdate = true;

  // Indicate the material needs update
  meshes[meshIdx].material.needsUpdate = true;
}

/**
* Lights
**/

// Add a point light with #fff color, .7 intensity, and 0 distance
var light = new THREE.PointLight( 0xffffff, 1, 0 );

// Specify the light's position
light.position.set(1, 1, 100);

// Add the light to the scene
scene.add(light)

/**
* Add Controls
**/

var controls = new THREE.TrackballControls(camera, renderer.domElement);

/**
* Handle window resizes
**/

window.addEventListener('resize', function() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  controls.handleResize();
});

/**
* Render!
**/

// The main animation function that re-renders the scene each animation frame
function animate() {
requestAnimationFrame( animate );
  renderer.render( scene, camera );
  controls.update();
}
animate();
* {
  margin: 0;
  padding: 0;
  background: #000;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/yale-dh-staging/tsne/assets/vendor/js/trackball-controls.js"></script>
<div id='loading'>Loading</div>

共有1个答案

麻鹏鹍
2023-03-14

这是一个已知的错误:https://github.com/mrdoob/three.js/issues/7179

必须使用,而不是通过索引访问器更改faceVertexUv。在faceVertexUv内的适当向量上设置()方法,例如:

if (geometry.faceVertexUvs[0][faceIdx]) {
    geometry.faceVertexUvs[0][faceIdx][0].set(xOffset, yOffset)
    geometry.faceVertexUvs[0][faceIdx][1].set(xOffset + width, yOffset)
    geometry.faceVertexUvs[0][faceIdx][2].set(xOffset + width, yOffset + height)
  } else {
    geometry.faceVertexUvs[0][faceIdx] = [
      new THREE.Vector2(xOffset, yOffset),
      new THREE.Vector2(xOffset + width, yOffset),
      new THREE.Vector2(xOffset + width, yOffset + height)
    ]
  }

完整示例:

/**
* Globals
**/

// Create a store for all images contained in the visualization
var imageList = null;

// Create a store for the image atlas files. Each key will represent
// the index position of the atlas file, and the value will point
// to the material at that index position
var materials = {32: {}, 64: {}};

// Create global configs for image and atlas sizing
var image, atlas;

// Create a store of meshes
var meshes = [];

/**
* Create Scene
**/

// Create the scene and a camera to view it
var scene = new THREE.Scene();

/**
* Camera
**/

// Specify the portion of the scene visiable at any time (in degrees)
var fieldOfView = 75;

// Specify the camera's aspect ratio
var aspectRatio = window.innerWidth / window.innerHeight;

/*
Specify the near and far clipping planes. Only objects
between those planes will be rendered in the scene
(these values help control the number of items rendered
at any given time)
*/
var nearPlane = 100;
var farPlane = 50000;

// Use the values specified above to create a camera
var camera = new THREE.PerspectiveCamera(
  fieldOfView, aspectRatio, nearPlane, farPlane
);

// Finally, set the camera's position
camera.position.z = 12000;
camera.position.y = -2000;

/**
* Lights
**/

// Add a point light with #fff color, .7 intensity, and 0 distance
var light = new THREE.PointLight( 0xffffff, 1, 0 );

// Specify the light's position
light.position.set(1, 1, 100);

// Add the light to the scene
scene.add(light)

/**
* Renderer
**/

// Create the canvas with a renderer
var renderer = new THREE.WebGLRenderer({ antialias: true });

// Add support for retina displays
renderer.setPixelRatio( window.devicePixelRatio );

// Specify the size of the canvas
renderer.setSize( window.innerWidth, window.innerHeight );

// Add the canvas to the DOM
document.body.appendChild( renderer.domElement );

/**
* Load External Data
**/

// Identify data endpoint
var dataUrl = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/data/';

// Create a store for image position information
var imagePositions = null;

// Load the image position JSON file
var fileLoader = new THREE.FileLoader();
fileLoader.load(dataUrl + 'image_tsne_projections.json', function(data) {
  imagePositions = JSON.parse(data);
  conditionallyBuildGeometries(32)
})

/**
* Load Atlas Textures
**/

// List of all textures to be loaded, the size of subimages
// in each, and the total count of atlas files for each size
var textureSets = {
  32: { size: 32, count: 5 },
  64: { size: 64, count: 20 }
}

// Create a texture loader so we can load our image files
var textureLoader = new THREE.TextureLoader();

function loadTextures(size) {
  for (var i=0; i<textureSets[size].count; i++) {
    var url = dataUrl + 'atlas_files/' + size + 'px/atlas-' + i + '.jpg';
    textureLoader.load(url, handleTexture.bind(null, size, i));
  }
}

// Create a material from the new texture and call
// the geometry builder if all textures have loaded 
function handleTexture(size, idx, texture) {
  var material = new THREE.MeshBasicMaterial({ map: texture });
  materials[size][idx] = material;
  conditionallyBuildGeometries(size, idx)
}

// If the textures and the mapping from image idx to positional information
// are all loaded, create the geometries
function conditionallyBuildGeometries(size, idx) {
  if (size === 32) {
    var nLoaded = Object.keys(materials[size]).length;
    var nRequired = textureSets[size].count;
    if (nLoaded === nRequired && imagePositions) {  
      document.querySelector('#loading').style.display = 'none';
      buildGeometry(size);
      loadTextures(64)
    }
  } else {
    updateGeometry(size, idx)
  }
}

loadTextures(32)

/**
* Build Image Geometry
**/

// Iterate over the textures in the current texture set
// and for each, add a new mesh to the scene
function buildGeometry(size) {
  setImageAndAtlasSize(size);
  for (var i=0; i<textureSets[size].count; i++) {
    // Create one new geometry per set of 1024 images
    var geometry = new THREE.Geometry();
    geometry.faceVertexUvs[0] = [];
    for (var j=0; j<atlas.cols*atlas.rows; j++) {
      geometry = updateVertices(geometry, i, j);
      geometry = updateFaces(geometry);
      geometry = updateFaceVertexUvs(geometry, j);
      if ((j+1)%1024 === 0) {
        buildMesh(geometry, materials[size][i]);
        var geometry = new THREE.Geometry();
      }
    }
  }
}

function setImageAndAtlasSize(size) {
  // Identify the subimage size in px (width/height) and the
  // size of the image as it will be displayed in the map
  image = { width: size,  height: size, shownWidth: 64, shownHeight: 64 };
  
  // Identify the total number of cols & rows in the image atlas
  atlas = { width: 2048, height: 2048, cols: 2048/size, rows: 2048/size };
}

// Get the x, y, z coords for the subimage at index position j
// of atlas in index position i
function getCoords(i, j) {
  var idx = (i * atlas.rows * atlas.cols) + j;
  var coords = imagePositions[idx];
  coords.x *= 2200;
  coords.y *= 1200;
  coords.z = (-200 + j/100);
  return coords;
}

// Add one vertex for each corner of the image, using the 
// following order: lower left, lower right, upper right, upper left
function updateVertices(geometry, i, j) {
  // Retrieve the x, y, z coords for this subimage
  var coords = getCoords(i, j);
  geometry.vertices.push(
    new THREE.Vector3(
      coords.x,
      coords.y,
      coords.z
    ),
    new THREE.Vector3(
      coords.x + image.shownWidth,
      coords.y,
      coords.z
    ),
    new THREE.Vector3(
      coords.x + image.shownWidth,
      coords.y + image.shownHeight,
      coords.z
    ),
    new THREE.Vector3(
      coords.x,
      coords.y + image.shownHeight,
      coords.z
    )
  );
  return geometry;
}

// Create two new faces for a given subimage, then add those
// faces to the geometry
function updateFaces(geometry) {
  // Add the first face (the lower-right triangle)
  var faceOne = new THREE.Face3(
    geometry.vertices.length-4,
    geometry.vertices.length-3,
    geometry.vertices.length-2
  )
  // Add the second face (the upper-left triangle)
  var faceTwo = new THREE.Face3(
    geometry.vertices.length-4,
    geometry.vertices.length-2,
    geometry.vertices.length-1
  )
  // Add those faces to the geometry
  geometry.faces.push(faceOne, faceTwo);
  return geometry;
}

function updateFaceVertexUvs(geometry, j) {  
  // Identify the relative width and height of the subimages
  // within the image atlas
  var relativeW = image.width / atlas.width;
  var relativeH = image.height / atlas.height;

  // Identify this subimage's offset in the x dimension
  // An xOffset of 0 means the subimage starts flush with
  // the left-hand edge of the atlas
  var xOffset = (j % atlas.cols) * relativeW;
  
  // Identify this subimage's offset in the y dimension
  // A yOffset of 0 means the subimage starts flush with
  // the bottom edge of the atlas
  var yOffset = 1 - (Math.floor(j/atlas.cols) * relativeH) - relativeH;

  // Determine the faceVertexUvs index position
  var faceIdx = 2 * (j%1024);

  // Use the xOffset and yOffset (and the knowledge that
  // each row and column contains only 32 images) to specify
  // the regions of the current image. Use .set() if the given
  // faceVertex is already defined, due to a bug in updateVertexUvs:
  // https://github.com/mrdoob/three.js/issues/7179
  if (geometry.faceVertexUvs[0][faceIdx]) {
    geometry.faceVertexUvs[0][faceIdx][0].set(xOffset, yOffset)
    geometry.faceVertexUvs[0][faceIdx][1].set(xOffset + relativeW, yOffset)
    geometry.faceVertexUvs[0][faceIdx][2].set(xOffset + relativeW, yOffset + relativeH)
  } else {
    geometry.faceVertexUvs[0][faceIdx] = [
      new THREE.Vector2(xOffset, yOffset),
      new THREE.Vector2(xOffset + relativeW, yOffset),
      new THREE.Vector2(xOffset + relativeW, yOffset + relativeH)
    ]
  }
  // Map the region of the image described by the lower-left, 
  // upper-right, and upper-left vertices to `faceTwo`
  if (geometry.faceVertexUvs[0][faceIdx+1]) {
    geometry.faceVertexUvs[0][faceIdx+1][0].set(xOffset, yOffset)
    geometry.faceVertexUvs[0][faceIdx+1][1].set(xOffset + relativeW, yOffset + relativeH)
    geometry.faceVertexUvs[0][faceIdx+1][2].set(xOffset, yOffset + relativeH)
  } else {
    geometry.faceVertexUvs[0][faceIdx+1] = [
      new THREE.Vector2(xOffset, yOffset),
      new THREE.Vector2(xOffset + relativeW, yOffset + relativeH),
      new THREE.Vector2(xOffset, yOffset + relativeH)
    ]
  }
  return geometry;
}

function buildMesh(geometry, material) {
  // Convert the geometry to a BuferGeometry for additional performance
  //var geometry = new THREE.BufferGeometry().fromGeometry(geometry);
  // Combine the image geometry and material into a mesh
  var mesh = new THREE.Mesh(geometry, material);
  // Set the position of the image mesh in the x,y,z dimensions
  mesh.position.set(0,0,0)
  // Add the image to the scene
  scene.add(mesh);
  // Save this mesh
  meshes.push(mesh);
  return mesh;
}

/**
* Update Geometries with new VertexUvs and materials
**/

function updateGeometry(size, idx) {
  // Update the image and atlas sizes
  setImageAndAtlasSize(size)
  // Update the appropriate material
  meshes[idx].material = materials[size][idx];
  meshes[idx].material.needsUpdate = true;
  // Update the facevertexuvs
  for (var j=0; j<atlas.cols*atlas.rows; j++) {
    meshes[idx].geometry = updateFaceVertexUvs(meshes[idx].geometry, j);
  }
  meshes[idx].geometry.uvsNeedUpdate = true;
  meshes[idx].geometry.verticesNeedUpdate = true;
}

/**
* Add Controls
**/

var controls = new THREE.TrackballControls(camera, renderer.domElement);

/**
* Handle window resizes
**/

window.addEventListener('resize', function() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
  controls.handleResize();
});

/**
* Render!
**/

// The main animation function that re-renders the scene each animation frame
function animate() {
requestAnimationFrame( animate );
  renderer.render( scene, camera );
  controls.update();
}
animate();
* {
  margin: 0;
  padding: 0;
  background: #000;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/yale-dh-staging/tsne/assets/vendor/js/trackball-controls.js"></script>
<div id='loading'>Loading</div>
 类似资料:
  • 问题内容: 我有一个针对ui-select2下拉菜单的手表设置(来自ui-bootstrap)。手表会在加载时触发,但不会在数据更改时触发,我不知道为什么。 不应用模型更改或不使用第三个参数进行相等性比较(至少来自我的代码)不是一个常见的问题。 我需要怎么做才能使其点火? 这是一个说明问题的小问题。 问题答案: 我修好了一些东西。 http://plnkr.co/edit/5Zaln7QT2gET

  • userNotesTable: 用户提醒表: 插入触发器: 更新触发器: 这是数据库的当前代码,以及提醒表的特定触发器。我遇到的困难是,从提醒表中的specific中的user notes表中选择特定的名称和额外的内容,所有这些都在更新触发器中。 插入时,和会被插入到提醒和搜索表中,但我希望能够使用特定名称和用户注释表中的额外内容更新搜索表,这可能吗?

  • 问题内容: 我目前正在使用基于Web的Twitter客户端,因此我使用了angular.js,node.js和socket.io。我通过socket.io将新的推文推到我的客户端,服务在其中等待新的推文。当一条新的推文到来时,该服务通过$ broadcast发送事件。 在我的控制器中是一个事件侦听器,其中传入的tweet在单独的函数中进行处理。此功能只是将新的推文推入我的推文范围。 现在,我的问题

  • 问题内容: 在oracle中,我可以指定列,这将引发触发器的触发: 现在,我想执行以下操作:当 只 更新 一 列时,我不希望触发触发器。这怎么可能? 我可以列出除那一列之外的所有列,该列不应引起触发器的触发。对于具有许多列的表而言,这非常麻烦。 另一种方法是使用像这样的UPDATING函数: 但是,如果我立即更改了COL1 和 COL3,则该语句的计算结果为false。那不是我想要的,因为我只想更

  • 问题内容: 我想知道是否有可能用JS触发CSS HOVER效果,而不必使用其他类… 我尝试使用触发效果,但这不会触发CSS悬停效果。 PS:我做了一个功能,可以帮助用户使用在线CMS。帮助功能通过在图像上四处移动来显示操作方法,以显示操作方法。虚拟光标可以单击内容,显示元素等。但是我希望该虚拟光标也可以触发CSS中设置的:hover效果。 问题答案: 我知道您要做什么,但为什么不简单地这样做: 该

  • 问题内容: 我有一个通过node.js运行的JS文件,因此通常我会打开一个终端窗口并输入类似内容,然后它会整天运行;好玩 然后,当我想重新启动它时,我按下Ctrl-c,然后退出。然后,我可以再次运行命令。 现在,我想做的是能够通过网页执行此操作,以便我的用户可以运行特定的JS文件,也可以“重新引导”它们。 因此有两个问题: 有可能,如果可以,我如何开始? 它安全吗?如果不安全,可以安全吗? 基于s