第134篇:解决浏览器的CORS跨域问题(CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome-untrusted, https, edge.)

发布时间 2023-03-27 22:09:30作者: 养肥胖虎

好家伙,

 

我继续尝试着将我的飞机大战使用ES6模块化分离开来,出了点问题

 

1.出现问题:

 

 

edge,chrome等一系列浏览器,会为了安全,禁止你跨域访问

 

目录如下:

 

 

主程序 

 index.html

 

main_1.js

 

main.js

 完整代码如下:

  1 /* //plane封装成类
  2 //实例化后使用
  3 //plane方法有:
  4     // cteate 
  5     config
  6     start
  7     stop
  8     pause
  9     
 10     
 11     */
 12 let plane = {
 13     create(dom) {
 14         let canvas = document.createElement('canvas');
 15         dom.appendChild(canvas);
 16         canvas.width = 480;
 17         canvas.height = 650;
 18 
 19         // 初始化画布对象
 20         // const canvas = document.getElementById("canvas");
 21         const context = canvas.getContext("2d");
 22 
 23         // 定义游戏的状态
 24         // 开始
 25         const START = 0;
 26         // 开始时
 27         const STARTING = 1;
 28         // 运行时
 29         const RUNNING = 2;
 30         // 暂停时
 31         const PAUSE = 3;
 32         // 结束时
 33         const END = 4;
 34 
 35         //创建一个配置文件 收藏所有的图片路径
 36         const IMAGES = {
 37             b: "img/bullet1.png",
 38             bg: "img/4.jpg",
 39             copyright: "img/shoot_copyright.png",
 40             pause: "img/game_pause.png",
 41             loading_frame: ["img/game_loading1.png", "img/game_loading2.png", "img/game_loading3.png",
 42                 "img/game_loading4.png"
 43             ],
 44             hero_frame_live: ["img/hero1.png", "img/hero2.png"],
 45             hero_frame_death: ["img/hero_blowup_n1.png", "img/hero_blowup_n2.png", "img/hero_blowup_n3.png",
 46                 "img/hero_blowup_n4.png"
 47             ],
 48             e1_live: ["img/enemy1.png"],
 49             e1_death: ["img/enemy1_down1.png", "img/enemy1_down2.png", "img/enemy1_down3.png", "img/enemy1_down4.png"],
 50             e2_live: ["img/enemy2.png"],
 51             e2_death: ["img/enemy2_down1.png", "img/enemy2_down2.png", "img/enemy2_down3.png", "img/enemy2_down4.png"],
 52             e3_live: ["img/enemy3_n1.png", "img/enemy3_n2.png"],
 53             e3_death: ["img/enemy3_down1.png", "img/enemy3_down2.png", "img/enemy3_down3.png", "img/enemy3_down4.png",
 54                 "img/enemy3_down5.png", "img/enemy3_down6.png"
 55             ],
 56             c1: "img/lanqiu.jpg"
 57         };
 58         //初始化各个图片
 59         const b = createImage(IMAGES.b);
 60         const bg = createImage(IMAGES.bg);
 61         const copyright = createImage(IMAGES.copyright);
 62         const pause = createImage(IMAGES.pause);
 63         const loading_frame = createImage(IMAGES.loading_frame);
 64         const hero_frame = {
 65             live: createImage(IMAGES.hero_frame_live),
 66             death: createImage(IMAGES.hero_frame_death),
 67         };
 68         const e1 = {
 69             live: createImage(IMAGES.e1_live),
 70             death: createImage(IMAGES.e1_death),
 71         };
 72         const e2 = {
 73             live: createImage(IMAGES.e2_live),
 74             death: createImage(IMAGES.e2_death),
 75         };
 76         const e3 = {
 77             live: createImage(IMAGES.e3_live),
 78             death: createImage(IMAGES.e3_death),
 79         };
 80         const c1 = createImage(IMAGES.c1);
 81 
 82         function createImage(src) {
 83             let img;
 84             if (typeof src === "string") {
 85                 img = new Image();
 86                 img.src = src;
 87             } else {
 88                 img = [];
 89                 for (let i = 0; i < src.length; i++) {
 90                     img[i] = new Image();
 91                     img[i].src = src[i];
 92                 }
 93             }
 94             return img;
 95         }
 96 
 97         //天空类的配置项
 98         const SKY = {
 99             bg: bg,
100             width: 480,
101             height: 650,
102             speed: 10,
103         };
104 
105         // 飞机加载界面的配置项
106         const LOADING = {
107             frame: loading_frame,
108             width: 186,
109             height: 38,
110             x: 0,
111             y: 650 - 38,
112             speed: 400,
113         };
114 
115         // 英雄配置项
116         const HERO = {
117             frame: hero_frame,
118             width: 99,
119             height: 124,
120             speed: 100,
121         };
122 
123         // 子弹配置项
124         const BULLET = {
125             img: b,
126             width: 9,
127             height: 21,
128         };
129 
130         //小敌机配置项
131         const E1 = {
132             type: 1,
133             width: 57,
134             height: 51,
135             life: 10,
136             score: 1,
137             frame: e1,
138             minSpeed: 20,
139             maxSpeed: 10
140         };
141         //中敌机配置项
142         const E2 = {
143             type: 2,
144             width: 69,
145             height: 95,
146             life: 50,
147             score: 5,
148             frame: e2,
149             minSpeed: 50,
150             maxSpeed: 20
151         };
152         //打敌机配置项
153         const E3 = {
154             type: 3,
155             width: 169,
156             height: 258,
157             life: 100,
158             score: 20,
159             frame: e3,
160             minSpeed: 100,
161             maxSpeed: 100
162         };
163         //奖励类配置项
164         const C1 = {
165             type: 4,
166             width: 75,
167             height: 75,
168             life: 1,
169             score: 1,
170             img: c1,
171             minSpeed: 5,
172             maxSpeed: 10
173         };
174 
175         //初始化一个天空类
176         class Sky {
177             constructor(config) {
178                 this.bg = config.bg;
179                 this.width = config.width;
180                 this.height = config.height;
181                 this.x1 = 0;
182                 this.y1 = 0;
183                 this.x2 = 0;
184                 this.y2 = -this.height;
185                 this.speed = config.speed;
186                 this.lastTime = new Date().getTime();
187             }
188             judge() {
189                 let currentTime = new Date().getTime();
190                 if (currentTime - this.lastTime > this.speed) {
191                     this.y1++;
192                     this.y2++;
193                     this.lastTime = currentTime;
194                 }
195                 if (this.y2 === 0) {
196                     this.y1 = 0;
197                     this.y2 = -this.height;
198                 }
199             }
200             paint(context) {
201                 context.drawImage(this.bg, this.x1, this.y1, this.width, this.height);
202                 context.drawImage(this.bg, this.x2, this.y2, this.width, this.height);
203             }
204         }
205 
206         // 初始化一个飞机界面加载类
207         class Loading {
208             constructor(config) {
209                 this.frame = config.frame;
210                 this.frameIndex = 0;
211                 this.width = config.width;
212                 this.height = config.height;
213                 this.x = config.x;
214                 this.y = config.y;
215                 this.speed = config.speed;
216                 this.lastTime = new Date().getTime();
217             }
218             judge() {
219                 const currentTime = new Date().getTime();
220                 if (currentTime - this.lastTime > this.speed) {
221                     this.frameIndex++;
222                     if (this.frameIndex === 4) {
223                         state = RUNNING;
224                     }
225                     this.lastTime = currentTime;
226                 }
227             }
228             paint(context) {
229                 context.drawImage(this.frame[this.frameIndex], this.x, this.y);
230             }
231         }
232 
233         // 初始化一个英雄类
234         class Hero {
235             constructor(config) {
236                 this.width = config.width;
237                 this.height = config.height;
238                 this.x = (480 - config.width) / 2;
239                 this.y = 650 - config.height;
240                 this.frame = config.frame;
241                 this.frameLiveIndex = 0;
242                 this.frameDeathIndex = 0;
243                 this.lastTime = new Date().getTime();
244                 this.speed = config.speed;
245                 this.img = null;
246                 this.live = true;
247                 this.lastShootTime = new Date().getTime();
248                 this.shootInterval = 50; //直接控制子弹刷新速率
249                 this.bulletList = [];
250                 this.destory = false;
251             }
252             judge() {
253                 const currentTime = new Date().getTime();
254                 if (currentTime - this.lastTime > this.speed) {
255                     if (this.live) {
256                         this.img = this.frame.live[this.frameLiveIndex++ % this.frame.live.length];
257                     } else {
258                         this.img = this.frame.death[this.frameDeathIndex++];
259                         if (this.frameDeathIndex === this.frame.death.length) {
260                             this.destory = true;
261                         }
262                     }
263                     this.lastTime = currentTime;
264                 }
265             }
266             paint(context) {
267                 context.drawImage(this.img, this.x, this.y, this.width, this.height);
268             }
269             shoot() {
270                 const currentTime = new Date().getTime();
271                 if (currentTime - this.lastShootTime > this.shootInterval) {
272                     let bullet = new Bullet(BULLET, this.x + this.width / 2 - BULLET.width / 2, this.y - BULLET.height);
273                     this.bulletList.push(bullet);
274                     bullet.paint(context);
275                     this.lastShootTime = currentTime;
276                 }
277             }
278             collide() {
279                 this.live = false;
280             }
281         }
282 
283         //初始化一个子弹类
284         class Bullet {
285             constructor(config, x, y) {
286                 this.img = config.img;
287                 this.width = config.width;
288                 this.height = config.height;
289                 this.x = x;
290                 this.y = y;
291                 this.destory = false;
292             }
293             paint(context) {
294                 context.drawImage(this.img, this.x, this.y);
295             }
296             move() {
297                 this.y -= 8;
298             }
299             outOfBounds() {
300                 return this.y < -this.height;
301             }
302             collide() {
303                 this.destory = true;
304             }
305         }
306 
307         // 初始化一个敌机类
308         class Enemy {
309             constructor(config) {
310                 this.type = config.type;
311                 this.width = config.width;
312                 this.height = config.height;
313                 this.x = Math.floor(Math.random() * (480 - config.width));
314                 this.y = -config.height;
315                 this.life = config.life;
316                 this.score = config.score;
317                 this.frame = config.frame;
318                 this.img = this.frame.live[0];
319                 this.live = true;
320                 this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;
321                 this.lastTime = new Date().getTime();
322                 this.deathIndex = 0;
323                 this.destory = false;
324             }
325             move() {
326                 const currentTime = new Date().getTime();
327                 if (currentTime - this.lastTime >= this.speed) {
328                     if (this.live) {
329                         this.img = this.frame.live[0];
330                         this.y++;
331                         this.lastTime = currentTime;
332                     } else {
333                         this.img = this.frame.death[this.deathIndex++];
334                         if (this.deathIndex === this.frame.death.length) {
335                             this.destory = true;
336                         }
337                     }
338                 }
339             }
340             paint(context) {
341                 context.drawImage(this.img, this.x, this.y);
342             }
343             outOfBounds() {
344                 if (this.y > 650) {
345                     return true;
346                 }
347             }
348             hit(o) {
349                 let ol = o.x;
350                 let or = o.x + o.width;
351                 let ot = o.y;
352                 let ob = o.y + o.height;
353                 let el = this.x;
354                 let er = this.x + this.width;
355                 let et = this.y;
356                 let eb = this.y + this.height;
357                 if (ol > er || or < el || ot > eb || ob < et) {
358                     return false;
359                 } else {
360                     return true;
361                 }
362             }
363             collide() {
364                 this.life--;
365                 if (this.life === 0) {
366                     this.live = false;
367                     score += this.score;
368                 }
369             }
370         }
371         //初始化奖励类
372         class award {
373             constructor(config) {
374                 this.type = config.type;
375                 this.width = config.width;
376                 this.height = config.height;
377                 this.x = Math.floor(Math.random() * (480 - config.width));
378                 this.y = -config.height;
379                 this.life = config.life;
380                 this.score = config.score;
381                 this.img = config.img;
382                 this.live = true;
383                 this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;
384                 this.lastTime = new Date().getTime();
385                 this.deathIndex = 0;
386                 this.destory = false;
387             }
388             move() {
389                 const currentTime = new Date().getTime();
390                 if (currentTime - this.lastTime >= this.speed) {
391                     if (this.live) {
392                         this.y = this.y + 6;
393                         this.lastTime = currentTime;
394                     } else {
395                         this.destory = true;
396 
397                     }
398                 }
399             }
400             paint(context) {
401                 context.drawImage(this.img, this.x, this.y, this.width, this.height);
402             }
403             outOfBounds() {
404                 if (this.y > 650) {
405                     return true;
406                 }
407             }
408             hit(o) {
409                 let ol = o.x;
410                 let or = o.x + o.width;
411                 let ot = o.y;
412                 let ob = o.y + o.height;
413                 let el = this.x;
414                 let er = this.x + this.width;
415                 let et = this.y;
416                 let eb = this.y + this.height;
417                 if (ol > er || or < el || ot > eb || ob < et) {
418                     return false;
419                 } else {
420                     return true;
421                 }
422             }
423             // collide() {
424             //   this.life--;
425             //   if (this.life === 0) {
426             //     this.live = false;
427             //     score += this.score;
428             //   }
429             // }
430         }
431         //初始化一个天空实例
432         const sky = new Sky(SKY);
433         //初始化一个飞机界面加载实例
434         const loading = new Loading(LOADING);
435         //初始化一个英雄实例 英雄是会变的
436         let hero = new Hero(HERO);
437         //state表示游戏的状态 取值必须是以上的五种状态
438         let state = START;
439         //score 分数变量 life 变量
440         let score = 0;
441         let life = 3;
442         //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态
443         canvas.addEventListener("click", () => {
444             if (state === START) {
445                 state = STARTING;
446             }
447         });
448         // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心
449         canvas.addEventListener("mousemove", (e) => {
450             let x = e.offsetX;
451             let y = e.offsetY;
452             hero.x = x - hero.width / 2;
453             hero.y = y - hero.height / 2;
454         });
455 
456         // //为canvas绑定一个屏幕触碰事件 触碰点正好在飞机图片的正中心
457         // canvas.addEventListener("touchstart",(e)=>{
458         //   let x = e.offsetX;
459         //   let y = e.offsetY;
460         //   hero.x = x - hero.width / 2;
461         //   hero.y = y - hero.height / 2;
462         // })
463         //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心
464         canvas.addEventListener("touchmove", (e) => {
465             // let x = e.pageX;
466             // let y = e.pageY;
467             console.log(e);
468             // let x = e.touches[0].clientX;
469             // let y = e.touches[0].clinetY;
470             let x = e.touches[0].pageX;
471             let y = e.touches[0].pageY;
472             // let x = e.touches[0].screenX;
473             // let y = e.touches[0].screenY;
474             let write1 = (document.body.clientWidth - 480) / 2;
475             let write2 = (document.body.clientHeight - 650) / 2;
476             hero.x = x - write1 - hero.width / 2;
477             hero.y = y - write2 - hero.height / 2;
478 
479             // hero.x = x - hero.width / 2;
480             // hero.y = y - hero.height / 2;
481             console.log(x, y);
482             console.log(document.body.clientWidth, document.body.clientHeight);
483             e.preventDefault(); // 阻止屏幕滚动的默认行为
484 
485         })
486         // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE
487         canvas.addEventListener("mouseleave", () => {
488             if (state === RUNNING) {
489                 state = PAUSE;
490             }
491         });
492 
493         // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING
494         canvas.addEventListener("mouseenter", () => {
495             if (state === PAUSE) {
496                 state = RUNNING;
497             }
498         });
499         // 碰撞检测函数
500         //此处的碰撞检测包括 
501         //1.子弹与敌机的碰撞
502         //2.英雄与敌机的碰撞
503         //3.英雄与随机奖励的碰撞
504         function checkHit() {
505             // 遍历所有的敌机
506             for (let i = 0; i < awards.length; i++) {
507                 //检测英雄是否碰到奖励类
508                 if (awards[i].hit(hero)) {
509                     //当然了,这个随机奖励的样式也要删了
510                     awards.splice(i, 1);
511                     //清除所有的敌机
512                     // for (let i = 0; i < enemies.length; i++) {
513                     //   enemies.splice(i, 1);
514                     // }
515                     enemies.length = 0;
516 
517                 }
518             }
519             for (let i = 0; i < enemies.length; i++) {
520                 //检测英雄是否撞到敌机
521                 if (enemies[i].hit(hero)) {
522                     //将敌机和英雄的destory属性改为true
523                     enemies[i].collide();
524                     hero.collide();
525                 }
526                 for (let j = 0; j < hero.bulletList.length; j++) {
527                     enemies[i].hit(hero.bulletList[j]);
528                     //检测子弹是否撞到敌机
529                     if (enemies[i].hit(hero.bulletList[j])) {
530                         //将敌机和子弹的destory属性改为true
531                         enemies[i].collide();
532                         hero.bulletList[j].collide();
533                     }
534                 }
535             }
536         }
537         //该变量中有所有的敌机实例
538         let enemies = [];
539         //该变量中存放所有的奖励实例
540         let awards = [];
541         //敌机产生的速率
542         let ENEMY_CREATE_INTERVAL = 800;
543         let ENEMY_LASTTIME = new Date().getTime();
544         // 全局函数 隔一段时间就来初始化一架敌机/奖励
545         function createComponent() {
546             const currentTime = new Date().getTime();
547             if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {
548                 let ran = Math.floor(Math.random() * 100);
549                 if (ran < 55) {
550                     enemies.push(new Enemy(E1));
551                 } else if (ran < 85 && ran > 55) {
552                     enemies.push(new Enemy(E2));
553                 } else if (ran < 95 && ran > 85) {
554                     enemies.push(new Enemy(E3));
555                 } else if (ran > 95) {
556                     awards.push(new award(C1));
557 
558                 }
559 
560                 ENEMY_LASTTIME = currentTime;
561             }
562         }
563         // 全局函数 来判断所有的子弹/敌人组件 "负责移动"
564         function judgeComponent() {
565             for (let i = 0; i < hero.bulletList.length; i++) {
566                 hero.bulletList[i].move();
567             }
568             for (let i = 0; i < enemies.length; i++) {
569                 enemies[i].move();
570             }
571             for (let i = 0; i < awards.length; i++) {
572                 awards[i].move();
573             }
574         }
575         // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板
576         function paintComponent() {
577             for (let i = 0; i < hero.bulletList.length; i++) {
578                 hero.bulletList[i].paint(context);
579             }
580             for (let i = 0; i < enemies.length; i++) {
581                 enemies[i].paint(context);
582             }
583             for (let i = 0; i < awards.length; i++) {
584                 awards[i].paint(context);
585             }
586             context.font = "20px 微软雅黑";
587             context.fillStyle = "green";
588             context.textAlign = "left";
589             context.fillText("score: " + score, 10, 20);
590             context.textAlign = "right";
591             context.fillText("life: " + life, 480 - 10, 20);
592             //重置样式
593             context.fillStyle = "black";
594             context.textAlign = "left";
595         }
596         // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄
597         function deleteComponent() {
598             if (hero.destory) {
599                 life--;
600                 hero.destory = false;
601                 if (life === 0) {
602                     state = END;
603                 } else {
604                     hero = new Hero(HERO);
605                 }
606             }
607             for (let i = 0; i < hero.bulletList.length; i++) {
608                 if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) {
609                     hero.bulletList.splice(i, 1);
610                 }
611             }
612             for (let i = 0; i < enemies.length; i++) {
613                 if (enemies[i].outOfBounds() || enemies[i].destory) {
614                     enemies.splice(i, 1);
615                 }
616             }
617         }
618 
619 
620 
621 
622         //当图片加载完毕时,需要做某些事情
623         bg.addEventListener("load", () => {
624             setInterval(() => {
625                 switch (state) {
626                     case START:
627                         sky.judge();
628                         sky.paint(context);
629                         let logo_x = (480 - copyright.naturalWidth) / 2;
630                         let logo_y = (650 - copyright.naturalHeight) / 2;
631                         context.drawImage(copyright, logo_x, logo_y);
632                         break;
633                     case STARTING:
634                         sky.judge();
635                         sky.paint(context);
636                         loading.judge();
637                         loading.paint(context);
638                         break;
639                     case RUNNING:
640                         sky.judge();
641                         sky.paint(context);
642                         hero.judge();
643                         hero.paint(context);
644                         hero.shoot();
645                         createComponent();
646                         judgeComponent();
647                         deleteComponent();
648                         paintComponent();
649                         checkHit();
650                         break;
651                     case PAUSE:
652                         let pause_x = (480 - pause.naturalWidth) / 2;
653                         let pause_y = (650 - pause.naturalHeight) / 2;
654                         context.drawImage(pause, pause_x, pause_y);
655                         break;
656                     case END:
657                         //给我的画笔设置一个字的样式
658                         //后面写出来的字都是这个样式的
659                         context.font = "bold 24px 微软雅黑";
660                         context.textAlign = "center";
661                         context.textBaseline = "middle";
662                         context.fillText("GAME_OVER", 480 / 2, 650 / 2);
663                         break;
664                 }
665             }, 10);
666         });
667 
668         //背景切换方法
669         function changebg() {
670             console.log("changebg方法被触发")
671             bg.src = "img/background.png"
672         }
673 
674     }
675 };
676 
677 
678 export {
679     plane
680 };
main.js代码

 

然后打开index.html

直接报错,跨域问题

 

2.解决问题:

网上搜了一大片问题解决方案:

方案一:使用npm模块 anywhere

 

 

 

anywhere可以将你的当前目录变成一个静态文件服务器的根目录。

全局安装:

npm install anywhere -g

在index.html目录下;

anywhere

 

 

 

 随后自动打开网页,不再报错

 

 

方案二:

使用Live Server插件

 

 

 

安装后,直接在右下角启动服务

 

 

 

 

方案三:

买个服务器,部署到服务器上

.....