the file protocol, file:// is a protocol like any other, namely http://, https://,
with some additional restrictions
when you referenced your sun。jpg, the browser took this to be a relative url and so looked to the
base URL of the document to be able to resolve it, when it discovered it was from the file://
protocol it applied restrictions, one of them being you cant read local files, the actual error
given is somewhat misleading
browsers have two native ways to access local files, the file input tag and drag and drop, both require
interaction from user, we shall have to utilise those to access our local files, failing that you will either need
a browser extension coupled with some form of executable or a http server
you can select which files you want to access using the file input tag, generate an internal url for them
and use them wherever you would use any other url
<!-- local-files-with-three-js。html -->
<html>
<head>
<style>
body {
margin : 40px;
font-family : arial;
}
input {
font-size : 16px;
padding : 5px;
}
#user > * {
margin-top : 20px;
}
#url {
display : flex;
gap : 20px;
align-items : center;
}
#url input {
width : 100%;
}
#file input {
width : 225px;
}
#mesh input {
width : 225px;
}
#three {
margin-top : 30px;
display : flex;
justify-content : center;
}
</style>
</head>
<body>
<div id=user>
<div id=url><input placeholder= paste url here, hit enter onchange= url_change(event) ></div>
<div id=file><input value= load texture from file type=button onclick= file_change(event) ></div>
<div id=mesh><input type=button value=mesh onclick= mesh(event) ></div>
</div>
<div id=three></div>
</body>
<script type=module>
import * as THREE from https://esm。run/three ;
window。onload=function(){
mesh();
//texture(files。read( sun。jpg ));
}//onload
window。url_change=function(e){
texture(e。target。value);
e。target。value = ;
}//url_change
window。file_change=function(e){
var input = document。createElement( input );
input。type = file ;
input。onchange = onchange;
input。click();
function onchange(){
var blob = input。files[0];
var url = URL。createObjectURL(blob);
texture(url);
}//onchange
}//file_change
window。mesh=function(){
var meshMaterial = new THREE。MeshPhongMaterial({color: lightblue ,emissive: blue ,flatShading:true});
draw(meshMaterial);
}//mesh
window。texture=function(url){
var texture = new THREE。TextureLoader()。load(url);
var material = new THREE。MeshBasicMaterial({map:texture});
draw(material);
}//texture
function draw(material){
var scene = new THREE。Scene();
scene。background = new THREE。Color( gray );
var camera = new THREE。PerspectiveCamera(75,1,1,50);
camera。position。z = 50;
var renderer = new THREE。WebGLRenderer();
renderer。setSize(300,300);
document。getElementById( three )。replaceChildren(renderer。domElement);
var lights = new THREE。DirectionalLight( white ,3);
lights。position。set(75,75,200);
scene。add(lights);
//var geometry = new THREE。BufferGeometry();
const geometry = new THREE。SphereGeometry(25, 32, 32);
const sphere = new THREE。Mesh(geometry,material);
scene。add(sphere);
(function render() {
sphere。rotation。y += 0。005;
renderer。render(scene,camera);
requestAnimationFrame(render);
})();
}//draw
</script>
<script>
console。clear();
var files = {};
files。read = filename=>localStorage[filename];
files。remove = filename=>delete localStorage[filename];
files。clear = ()=>localStorage。clear();
files。list = ()=>{for(var key in {。。。localStorage})console。log(key)};
//files。clear();
files。list();
var root = document。createElement( div );
root。style。padding = 20px ;
root。style。border = 2px dashed blue ;
document。body。insertBefore(root,document。body。firstChild);
btn( select persistent files ,create);
btn( clear persistent files ,files。clear);
btn( list persistent files ,files。list);
function btn(value,onclick){
var input = document。createElement( input );
input。value = value
input。type = button ;
input。onclick = onclick;
input。style。marginRight = 20px ;
root。append(input);
}//btn
function create(e){
var input = document。createElement( input );
input。type = file ;
input。multiple = true;
input。onchange = onchange;
input。click();
function onchange(e){
[。。。input。files]。forEach(async file=>{
console。log(file。name);
var url = await datauri(file);
localStorage[file。name] = url;
});
}//onchange
}//create
async function datauri(file){
var i = file。name。lastIndexOf( 。 );
var ext = file。name。slice(i+1);
var mime = image/ +ext;
var buf = await file。arrayBuffer();
var bytes = new Uint8Array(buf);
var binary = ;
var n = bytes。byteLength;
for(var i=0;i<n;i++){
binary += String。fromCharCode(bytes[i]);
}//for
var b64 = window。btoa(binary);
var datauri = data: +mime+ ;base64, +b64;
return datauri;
}//datauri
</script>
</html>
https://jsbin。com/zosanurafo/
its quite cumbersome having to select which files you want to access every time you reload or change
page, so i added the above script which allows persistent storage of files in localStorage, theres a limit
of about 5MB
ok the above script will allow you to click the button "select files", and select multiple files, they will
be available ( according to my brief testing in chrome ) across the entire file:// protocol, across page
reloads and page navigation。 anywhere you want to use these files just call
files。read(filename) // e。g: files。read( sun。jpg )
// new THREE。TextureLoader()。load(files。read("sun。jpg"));
with regards to CORS itself, the file:// protocol is still subject to CORS policies the same as any other
protocol, for the file:// protocol, document。domain=null, or a special domain that always fails any domain
check
that being said servers can send a CORS response, determined by access-control-* headers, if the
appropiate CORS headers are received, the page can access certain restricted parts of that response
for pages under the file:// protocol the document。domain is effectively null, therefore any response will have to contain the response header Access-Control-Allow-Origin:* for javascript to be
able to read the data, which is required for say THREE。textureLoader to work
。
熟悉服务器
join us in the stackoverflow javascript chat
页: 1
。
i 回答另一个类似问题
stackoverflow : How to make a file:// file connect to the node。js server with socket。io
。
here you can try this to get you started, you ll need the internet to load three。js in this model
利用文件纽伦从当地硬拷贝中挑选文件
function url_change(e){
texture(e。target。value);
}
function file_change(e){
var blob = e。target。files[0];
var url = URL。createObjectURL(blob);
texture(url);
}
body {
display:flex;
align-items:top;
gap:20px;
}
input {
font-size:16px;
padding:5px;
width:250px;
margin-left:20px;
}
span {
display:inline-block;
}
<body>
<span></span>
<div>
<input type=file onchange= file_change(event) >
<br>
url<input onchange= url_change(event) >
<br>
<input type=button value=mesh onclick= mesh(event) >
</div>
</body>
<script type=module>
import * as THREE from https://esm。run/three ;
window。mesh=function(){
var meshMaterial = new THREE。MeshPhongMaterial({color: lightblue ,emissive: blue ,flatShading:true});
ready(meshMaterial);
}
window。texture=function(url){
const cargador = new THREE。TextureLoader()。load(url);
const cargaTextura = new THREE。MeshBasicMaterial({ map: cargador });
ready(cargaTextura);
}
function ready(material){
var scene = new THREE。Scene();
scene。background = new THREE。Color( gray );
var camera = new THREE。PerspectiveCamera(75,1,1,50);
camera。position。z = 50;
var renderer = new THREE。WebGLRenderer();
renderer。setSize(300,300);
document。body。querySelector( span )。replaceChildren(renderer。domElement);
var lights = new THREE。DirectionalLight( white ,3);
lights。position。set(75,75,200);
scene。add(lights);
//var geometry = new THREE。BufferGeometry();
const geometry = new THREE。SphereGeometry(25, 32, 32);
const sphere = new THREE。Mesh(geometry,material);
scene。add(sphere);
(function render() {
sphere。rotation。y += 0。005;
renderer。render(scene,camera);
requestAnimationFrame(render);
})();
}//setup
mesh();
</script>
您可以把ur带入文字领域,并进入媒体。
页: 1