使用three.js和其他工具将2D图像转换为3D

时间:2018-08-16 22:01:45

标签: javascript html three.js webgl blender

我有一张要制作成3D的数据可视化图像。我想知道如何使用three.js和其他可能的工具将此图像转换为3D。我不知道该怎么办。

我听说有一个叫做WebGL Javascript API的东西,所以也许我可以使用它,但是我不知道如何开始以及在这种情况下是否可以使用它。我还在某处读到,如果没有有关第三维的某些信息,则无法从2D图像制作3D图像。这些丢失的信息可能来自第二张照片,人工智能软件或3D数字模型。

我还读到我可以在Blender中制作图像的3D模型,然后将其导入three.js。

有人知道我该怎么做吗?

我想尝试在JS小提琴中进行编码,除非JS小提琴之外需要其他软件/工具。我看到您可以在其中导入three.js库。

我目前所做的可视化是

我需要的可视化代码是:

$(function() {
  var dataEx = [
      ['1 Visit', 352000],
      ['2 Visits', 88000],
      ['3+ Visits', 42000]
    ],
    len = dataEx.length,
    sum = 0,
    minHeight = 0.05,
    data = [];
    
   //specify your percent of prior visit value manually here:
   
   var perc = [100, 25, 48];

  for (var i = 0; i < len; i++) {
    sum += dataEx[i][1];
  }

  for (var i = 0; i < len; i++) {
    var t = dataEx[i],
      r = t[1] / sum;
    data[i] = {
      name: t[0],
      y: (r > minHeight ? t[1] : sum * minHeight),
      percent: perc[i],   // <----- this here is manual input
			//percent: Math.round(r * 100),    <--- this here is mathematical
      label: t[1]
    }
  }
  console.log(dataEx, data)
  $('#container').highcharts({
    chart: {
      type: 'funnel',
      marginRight: 100,


      events: {
        load: function() {
          var chart = this;
          Highcharts.each(chart.series[0].data, function(p, i) {
          	var bBox = p.dataLabel.getBBox()
            p.dataLabel.attr({
              x: (chart.plotWidth - chart.plotLeft) / 2,
              'text-anchor': 'middle',
              y: p.labelPos.y - (bBox.height / 2)
            })
          })
        },
        redraw: function() {
          var chart = this;
          Highcharts.each(chart.series[0].data, function(p, i) {
            p.dataLabel.attr({
              x: (chart.plotWidth - chart.plotLeft) / 2,
              'text-anchor': 'middle',
              y: p.labelPos.y - (bBox.height / 2)
            })
          })
        }
      },
    },
    
    //Manually changing the default colors of each category of series
    colors: ['#FF5733', '#FFA533', '#1FC009'],

    title: {
      text: 'New Guest Return Funnel',
      x: -45
    },
    
    credits: {
    
    	enabled: false
    },
    
    tooltip: {
      //enabled: false
      formatter: function() {
        return '<b>' + this.key +
          '</b><br/>Percent of Prior Visit: '+ this.point.percent + '%<br/>Guests: ' + Highcharts.numberFormat(this.point.label, 0);
      }
    },
    plotOptions: {
      series: {


        allowPointSelect: true,
        borderWidth: 12,

        animation: {
          duration: 400
        },


        dataLabels: {
          enabled: true,

          connectorWidth: 0,
          distance: 0,

          formatter: function() {
            var point = this.point;
            console.log(point);
            return '<b>' + point.name + '</b> (' + Highcharts.numberFormat(point.label, 0) + ')<br/>' + point.percent + '%';
          },
          minSize: '10%',
          color: 'black',
          softConnector: true
        },

        neckWidth: '30%',
        neckHeight: '0%',
        width: '50%',
        height: '110%'


        //old options are as follows:

        //neckWidth: '50%',
        //neckHeight: '50%',
        //-- Other available options
        //height: '200'
        // width: pixels or percent
      }
    },
    legend: {
      enabled: false
    },
    series: [{
      name: 'Unique users',
      data: data
    }]
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/funnel.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>

<div id="container" style="width: 500px; height: 400px; margin: 0 auto"></div>

1 个答案:

答案 0 :(得分:0)

我给你做了一个快速而肮脏的例子。希望它能给您一些想法。

var dataEx = [
    ['1 Visit', 352000],
    ['2 Visits', 88000],
    ['3+ Visits', 42000]
  ],
  len = dataEx.length,
  sum = 0,
  minHeight = 0.05,
  data = [];

//specify your percent of prior visit value manually here:

var perc = [100, 25, 48];

for (var i = 0; i < len; i++) {
  sum += dataEx[i][1];
}

for (var i = 0; i < len; i++) {
  var t = dataEx[i],
    r = t[1] / sum;
  data[i] = {
    name: t[0],
    y: (r > minHeight ? t[1] : sum * minHeight),
    percent: perc[i], // <----- this here is manual input
    //percent: Math.round(r * 100),    <--- this here is mathematical
    label: t[1]
  }
}
console.log(dataEx, data)



var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
  45, // Field of view
  w / h, // Aspect ratio
  0.1, // Near
  10000 // Far
);
controls = new THREE.OrbitControls(camera, renderer.domElement);
camera.position.set(0, 20, 15);
camera.lookAt(new THREE.Vector3(0, 60, 0));
controls.target.set(0, 10, 0);

var light = new THREE.PointLight(0xFFFFFF);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var light2 = new THREE.PointLight(0xFFFFFF);
light2.position.set(-20, 20, -20);
scene.add(light2);
var light3 = new THREE.PointLight(0xFFFFFF);
light3.position.set(-20, -20, -20);
scene.add(light3);

function makeCanvasTexture(color, text) {
  var canvas = document.createElement('canvas');
  canvas.width = canvas.height = 256;
  var ctx = canvas.getContext('2d');
  ctx.textAlign = "center";
  ctx.fillStyle = color;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = 'black';
  ctx.font = "30px Arial";
  ctx.fillText(text, (canvas.width / 2) | 0, (canvas.height / 2) | 0);

  var tex = new THREE.Texture(canvas)
  tex.minFilter = THREE.LinearMipMapLinearFilter;
  tex.magFilter = THREE.LinearFilter;
  tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
  tex.needsUpdate = true;
  return tex;
}

function makePlane(color, text, percent, position) {
  var geom = new THREE.PlaneGeometry(1, 1);
  var material = new THREE.MeshLambertMaterial({
    color: 'white',
    side: THREE.DoubleSide,
    map: makeCanvasTexture(color, text)
  });
  var npct = percent / 100;
  material.map.repeat.set(1, npct);
  material.map.offset.set(0, 0.5 * (1 - npct));
  var mesh = new THREE.Mesh(geom, material);

  mesh.position.y = position;
  mesh.scale.y *= percent / 100;
  return mesh;
}

renderer.setClearColor(0xdddddd, 1);
var root = new THREE.Object3D();
scene.add(root);
root.scale.multiplyScalar(10);
var yOffset = 0;
var colors = ['red', 'green', 'yellow']
for (var i = 0; i < data.length; i++) {
  yOffset += data[i].percent / 200
  var plane = makePlane(colors[i], data[i].name, data[i].percent, yOffset);
  root.add(plane);
  yOffset += data[i].percent / 200
  yOffset += 0.05
}

(function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
  var pnow = performance.now()*0.001;
  controls.target.y = (Math.sin(pnow)*10)+10
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>