在父项 div 中拟合 canvas

Fitting canvas in parent div

我正在努力让我的 canvas 适合 div。

    // Make the Canvas Responsive

    window.onload = function(){
      wih = window.innerHeight;
      wiw = window.innerWidth;
    }
    window.onresize = function(){
      wih = window.innerHeight;
      wiw = window.innerWidth;
    }

    // Define the min and max Values for the Randomize Function.
    radiusMin = 1;
    radiusMax = 40;
    tubeMin = 1;
    tubeMax = 40;
    radialSegmentsMin = 1;
    radialSegmentsMax = 800;
    tubularSegmentsMin = 1;
    tubularSegmentsMax = 30;
    pMin = 1;
    pMax = 20;
    qMin = 1;
    qMax = 20;
    heightScaleMin = 0;
    heightScaleMax = 5;


    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(
        45, // fov (45 / 60)
        window.innerWidth / window.innerHeight, // wiw / wih,
        0.1,
        1000
    );

    // Create a WebGLRenderer
    var webGLRenderer = new THREE.WebGLRenderer();
    webGLRenderer.setClearColor(new THREE.Color(0x000000, 1.0));
    webGLRenderer.setSize(window.innerWidth, window.innerHeight);
    webGLRenderer.shadowMapEnabled = true;

    // Append the output of the renderer to the html element
    document.getElementById("WebGL-output").append(webGLRenderer.domElement);
    var step = 0;
    var knot;

    // Keep Aspect Ratio on Resize
    window.addEventListener("resize", onWindowResize, false);
    function onWindowResize() {
      camera.aspect = wiw / wih;
      camera.updateProjectionMatrix();
      webGLRenderer.setSize(window.innerWidth, window.innerHeight);
    }

    // Position and point the camera to the center of the scene
    camera.position.x = -30;
    camera.position.y = -40;
    camera.position.z = 50;
    camera.lookAt(new THREE.Vector3(10, 0, 0));
    var clock = new THREE.Clock();
    var trackballControls = new THREE.TrackballControls(camera, webGLRenderer.domElement);
    trackballControls.rotateSpeed = 4.0;
    trackballControls.zoomSpeed = 1.0;
    trackballControls.panSpeed = 1.0;
    trackballControls.noZoom = false;
    trackballControls.noPan = true;
    trackballControls.staticMoving = false;
    trackballControls.dynamicDampingFactor = 0.3;

    // Setup Controls for dat.GUI
    var controls = new function() {
      // Default Values
      this.color = "#7a4d0c";
      this.radius = 22;
      this.tube = 32;
      this.radialSegments = 800;
      this.tubularSegments = 12;
      this.p = 10; // wind p times around its axis of rotational symmetry
      this.q = 14; // wind q times around a circle in the interior of the torus
      this.heightScale = 2;
      this.asParticles = true;
      this.rotate = true;
      this.animate = false; // Animates radialSegments
      this.randomize = false; // Randomize Mesh

      this.redraw = function() {
        // Remove the old plane
        if (knot) scene.remove(knot);
        // Create a new one
        var geom = new THREE.TorusKnotGeometry(
            controls.radius,
            controls.tube,
            Math.round(controls.radialSegments),
            Math.round(controls.tubularSegments),
            Math.round(controls.p),
            Math.round(controls.q),
            controls.heightScale,
            controls.color
        );

        if (controls.asParticles) {
          knot = createParticleSystem(geom);
        } else {
          knot = createMesh(geom);
        }
        // Add it to the scene.
        scene.add(knot);
      };
    }();

    var gui = new dat.GUI({
      resizable : false
    });
    gui.addColor(controls, "color").onChange(controls.redraw);
    gui.add(controls, "radius", radiusMin, radiusMax).onChange(controls.redraw);
    gui.add(controls, "tube", tubeMin, tubeMax).onChange(controls.redraw);
    gui.add(controls, "radialSegments", radialSegmentsMin, radialSegmentsMax).step(1).onChange(controls.redraw);
    gui.add(controls, "tubularSegments", tubularSegmentsMin, tubularSegmentsMax).step(1).onChange(controls.redraw);
    gui.add(controls, "p", pMin, pMax).step(1).onChange(controls.redraw);
    gui.add(controls, "q", qMin, qMax).step(1).onChange(controls.redraw);
    gui.add(controls, "heightScale", heightScaleMin, heightScaleMax).onChange(controls.redraw);
    gui.add(controls, "asParticles").onChange(controls.redraw);
    gui.add(controls, "rotate").onChange(controls.redraw);
    gui.add(controls, "animate").onChange(controls.redraw);
    gui.add(controls, "randomize").onChange(controls.redraw);

    gui.close();
    controls.redraw();

    render();

    // From THREE.js examples
    // Create Sprites for the particleSystem
    function generateSprite() {
      var canvas = document.createElement("canvas");
      canvas.width = 16;
      canvas.height = 16;

      var context = canvas.getContext("2d");
      var gradient = context.createRadialGradient(
          canvas.width / 2,
          canvas.height / 2,
          0,
          canvas.width / 2,
          canvas.height / 2,
          canvas.width / 2
      );
      gradient.addColorStop(0.0, controls.color);
      gradient.addColorStop(0.2, controls.color);
      gradient.addColorStop(0.4, controls.color);
      gradient.addColorStop(1.0, "rgba(0,0,0,1)");

      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);

     var texture = new THREE.Texture(canvas);
      texture.needsUpdate = true;
      return texture;
    }

    // Create a particleSystem and use the Sprites
    function createParticleSystem(geom) {
      var material = new THREE.ParticleBasicMaterial({
        color: 0xffffff,
        size: 2,
        transparent: true,
        blending: THREE.AdditiveBlending, // Time to Shine!
        map: generateSprite()
      });

      var system = new THREE.ParticleSystem(geom, material);
      system.sortParticles = true;
      return system;
      }

目前,它想要占据整个宽度,因为我用 CSS 编辑了它并且只接受 "Important" 标签。 div 在平板电脑和台式机上为 50vw,但在移动设备上为 100vw。问题是在移动期间,canvas 想要忽略告诉它调整大小到 100vw 的@media 样式;;;;如果这个愚蠢的 canvas 只是坚持 div 的宽度,它就会起作用。

我在Javascript方面还是一个很大的初学者,所以非常欢迎任何解释。

canvas 需要适合 DIV,这样当布局响应移动设备时,它会正常运行。

不确定这是否适合您和您的情况,但尝试没有坏处...

关键是window.matchMedia。传递给它的媒体查询字符串与 CSS 媒体查询中使用的相同:

const mq = window.matchMedia( "(min-width: 500px)" );

if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}

您还可以添加一个在检测到更改时触发的事件侦听器:

// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}

// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}

}

如果您希望渲染器遵守容器的宽度和高度 div,您需要检查该容器 div 的宽度和高度,而不是整个 window ]:

// Save reference of the parentDiv to be used later
var parent = document.getElementById('parentDiv');
parent.append(webGLRenderer.domElement);

// When window is resized
resizeRenderer() {
    // Get width & height of parentDiv
    var width = parent.clientWidth;
    var height = parent.clientHeight;
    webGLRenderer.setSize(width, height);
}

// Add window resize listener
window.addEventListener('resize', resizeRenderer);

// Force renderer resizing once
resizeRenderer();

这样,它将尊重您为 CSS 中的 parentDiv 建立的任何媒体查询。