on stats-world: adjust some lighting and position, and add an attempt at a screen-capture
This commit is contained in:
@@ -39,7 +39,7 @@
|
|||||||
- .5 make advanced features harder to access
|
- .5 make advanced features harder to access
|
||||||
|
|
||||||
- Release Minimum Viable Product :
|
- Release Minimum Viable Product :
|
||||||
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world).
|
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world, cannot screenshot).
|
||||||
|
|
||||||
- Stats :
|
- Stats :
|
||||||
- 01 point out user's location on the world
|
- 01 point out user's location on the world
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class World {
|
|||||||
this.lights = [];
|
this.lights = [];
|
||||||
this.bushes = [];
|
this.bushes = [];
|
||||||
|
|
||||||
// Initializae Loop
|
// Initialize Loop
|
||||||
this.loop = new Loop(this.camera, this.scene, this.renderer);
|
this.loop = new Loop(this.camera, this.scene, this.renderer);
|
||||||
|
|
||||||
container.append(this.renderer.domElement);
|
container.append(this.renderer.domElement);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ function createCamera() {
|
|||||||
35, // fov = Field Of View
|
35, // fov = Field Of View
|
||||||
1, // aspect ratio (dummy value)
|
1, // aspect ratio (dummy value)
|
||||||
0.1, // near clipping plane
|
0.1, // near clipping plane
|
||||||
300 // far clipping plane
|
350 // far clipping plane
|
||||||
);
|
);
|
||||||
|
|
||||||
// move the camera back so we can view the scene
|
// move the camera back so we can view the scene
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { DirectionalLight, DirectionalLightHelper } from "three";
|
|||||||
function createLights(color) {
|
function createLights(color) {
|
||||||
const light = new DirectionalLight(color, 4);
|
const light = new DirectionalLight(color, 4);
|
||||||
const lightHelper = new DirectionalLightHelper(light, 0);
|
const lightHelper = new DirectionalLightHelper(light, 0);
|
||||||
light.position.set(60, 60, 30);
|
light.position.set(60, 100, 30);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
light.tick = () => {};
|
light.tick = () => {};
|
||||||
|
|||||||
2
src/components/World/systems/controls.js
vendored
2
src/components/World/systems/controls.js
vendored
@@ -26,6 +26,8 @@ function createControls(camera, canvas) {
|
|||||||
controls.enableDamping = true;
|
controls.enableDamping = true;
|
||||||
|
|
||||||
//controls.enableZoom = false;
|
//controls.enableZoom = false;
|
||||||
|
controls.maxDistance = 250;
|
||||||
|
|
||||||
//controls.enablePan = false;
|
//controls.enablePan = false;
|
||||||
|
|
||||||
controls.tick = () => controls.update();
|
controls.tick = () => controls.update();
|
||||||
|
|||||||
@@ -54,21 +54,115 @@
|
|||||||
Your Statistics
|
Your Statistics
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<button class="float-right" @click="captureGraphics()">Screenshot</button>
|
||||||
|
|
||||||
<!-- Another place to play with the sizing is in Resizer.setSize -->
|
<!-- Another place to play with the sizing is in Resizer.setSize -->
|
||||||
<div id="scene-container" class="h-screen"></div>
|
<div id="scene-container" class="h-screen"></div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { SVGRenderer } from "three/addons/renderers/SVGRenderer.js";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { World } from "@/components/World/World.js";
|
import { World } from "@/components/World/World.js";
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class StatisticsView extends Vue {
|
export default class StatisticsView extends Vue {
|
||||||
|
world: World;
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const container = document.querySelector("#scene-container");
|
const container = document.querySelector("#scene-container");
|
||||||
const world = new World(container);
|
const newWorld = new World(container);
|
||||||
world.start();
|
newWorld.start();
|
||||||
|
this.world = newWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
public captureGraphics() {
|
||||||
|
/**
|
||||||
|
// from https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#examples
|
||||||
|
// Adds a blank image
|
||||||
|
const dataBlob = document
|
||||||
|
.querySelector("#scene-container")
|
||||||
|
.firstChild.toBlob((blob) => {
|
||||||
|
const newImg = document.createElement("img");
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
newImg.onload = () => {
|
||||||
|
// no longer need to read the blob so it's revoked
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
newImg.src = url;
|
||||||
|
document.body.appendChild(newImg);
|
||||||
|
});
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
// Yields a blank page with the iframe below
|
||||||
|
const dataUrl = document
|
||||||
|
.querySelector("#scene-container")
|
||||||
|
.firstChild.toDataURL("image/png");
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
// Yields a blank page with the iframe below
|
||||||
|
const dataUrl = this.world.renderer.domElement.toDataURL("image/png");
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
// Show the image in a new tab
|
||||||
|
const iframe = `
|
||||||
|
<iframe
|
||||||
|
src="${dataUrl}"
|
||||||
|
frameborder="0"
|
||||||
|
style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>`;
|
||||||
|
const win = window.open();
|
||||||
|
win.document.open();
|
||||||
|
win.document.write(iframe);
|
||||||
|
win.document.close();
|
||||||
|
**/
|
||||||
|
|
||||||
|
// from https://stackoverflow.com/a/17407392/845494
|
||||||
|
// This yields a file with funny formatting.
|
||||||
|
//const image = const dataUrl.replace("image/png", "image/octet-stream");
|
||||||
|
|
||||||
|
/**
|
||||||
|
// Yields a blank image at the bottom of the page
|
||||||
|
// from https://discourse.threejs.org/t/save-screenshot-on-server/39900/3
|
||||||
|
const img = new Image();
|
||||||
|
img.src = this.world.renderer.domElement.toDataURL();
|
||||||
|
document.body.appendChild(img);
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This yields an SVG that only shows white and black highlights
|
||||||
|
// from https://stackoverflow.com/questions/27632621/exporting-from-three-js-scene-to-svg-or-other-vector-format
|
||||||
|
**/
|
||||||
|
const rendererSVG = new SVGRenderer();
|
||||||
|
rendererSVG.setSize(window.innerWidth, window.innerHeight);
|
||||||
|
rendererSVG.render(this.world.scene, this.world.camera);
|
||||||
|
//document.body.appendChild(rendererSVG.domElement);
|
||||||
|
ExportToSVG(rendererSVG, "test.svg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ExportToSVG(rendererSVG, filename) {
|
||||||
|
const XMLS = new XMLSerializer();
|
||||||
|
const svgfile = XMLS.serializeToString(rendererSVG.domElement);
|
||||||
|
const svgData = svgfile;
|
||||||
|
const preface = '<?xml version="1.0" standalone="no"?>\r\n';
|
||||||
|
const svgBlob = new Blob([preface, svgData], {
|
||||||
|
type: "image/svg+xml;charset=utf-8",
|
||||||
|
});
|
||||||
|
const svgUrl = URL.createObjectURL(svgBlob);
|
||||||
|
const downloadLink = document.createElement("a");
|
||||||
|
|
||||||
|
downloadLink.href = svgUrl;
|
||||||
|
downloadLink.download = filename;
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user