原生微信小程序AR(扫描指定图片显示glb模型)

news2024/9/24 3:21:52

效果

ar案例视频

准备:需要准备要扫描的图片地址和扫描成功后显示的模型
1.在components创建组件
在这里插入图片描述
index.js文件代码

Component({
  properties: {
    title: {
      type: String,
      value: '',
    },
    intro: {
      type: String,
      value: '',
    },
    hint: {
      type: String,
      value: '',
    },
    code: {
      type: String,
      value: '',
    },
    json: {
      type: String,
      value: '',
    },
    js: {
      type: String,
      value: '',
    },
    showBackBtn: {
      type: Boolean,
      value: false,
    },
  },
  data: {
  },
  lifetimes: {
    attached() {
      wx.xrTitle = this.data.title;
    }
  },
  methods: {
    onClickBack() {
      wx.navigateBack()
    },
  }
})

index.json代码

{
  "component": true,
  "usingComponents": {}
}

index.wxml代码

<view class="demo-wrap">
  <scroll-view class="demo-viewer" scroll-y="{{true}}">
    <block bind:sceneReady="handleSceneReady">
      <slot></slot>
    </block>
    <view class="intro">
      <view class="intro-detail">
        <view class="intro-title" ><text>{{title}}</text> <button class="share" open-type="share">分享给好友</button></view>
        <view class="description" >{{intro}}</view>
      </view>
    </view>
    <view wx:if="{{hint.length > 0}}">
      <view class="hint-wrap">
        <text class="hint-words" >{{hint}}</text>
      </view>
    </view>
    <view wx:if="{{code.length > 0}}">
      <view class="intro">
        <view class="intro-detail">
          <view class="title">代码演示</view>
          <view class="code-inner">
            <rich-text nodes="{{code}}"></rich-text>
          </view>
        </view>
      </view>
    </view>
    <view wx:if="{{js.length > 0}}">
      <view class="intro">
        <view class="intro-detail">
          <view class="title">脚本演示</view>
          <view class="code-inner">
            <rich-text nodes="{{js}}"></rich-text>
          </view>
        </view>
      </view>
    </view>
    <view wx:if="{{json.length > 0}}">
      <view class="intro">
        <view class="intro-detail">
          <view class="title">动画数据结构</view>
          <view class="code-inner">
            <rich-text nodes="{{json}}"></rich-text>
          </view>
        </view>
      </view>
    </view>
    <view class="holder"></view>
  </scroll-view>
  <view class="back-btn-wrap" wx:if="{{showBackBtn}}" bind:tap="onClickBack">
    <view class="back-line-t"></view>
    <view class="back-line-b"></view>
  </view>
</view>

index.wxss代码

.demo-wrap {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
.demo-viewer {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

.holder {
  height: 60rpx;
}

.hint-wrap {
  text-align: center;
}

.hint-words {
  display: inline-block;
  color: #000;
  text-align:center;
  font-weight:bold;
  max-width: 300px;
  padding: 10px 20px;
  border: 2px dashed #000;
  background-color: #fff;
}

.intro {
  display: block;
  margin: 20rpx 0;
  background: #fff;
}

.intro .title {
  font-size: 36rpx;
  padding-bottom: 20rpx;
}

.intro .description {
  color: #8f8f8f;
  font-size: 28rpx;
}

.intro-detail {
  padding: 30rpx;
}


.code-inner {
  margin: 0rpx;
  padding: 30rpx;
  font-size: 30rpx;
  background-color: #f9f9fa;
}

.code-inner rich-text {
  word-wrap: break-word;
}

.block-name {
  display: inline-block;
  color: #b457ff;
}

.attr-name {
  display: inline-block;
  color: #ff4d00;
}

.ml20 {
  margin-left: 20rpx;
}

.intro-title {
  font-size: 30rpx;
  font-weight: bold;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 24rpx;
}

.share {
  margin: 0 !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  padding: 0;
  width: 160rpx !important;
  background: none;
  font-size: 28rpx;
  color: #ff4d00;
}

.back-btn-wrap {
  position: absolute;
  left: 30rpx;
  top: 100rpx;
  width: 90rpx;
  height: 80rpx;
}
.back-line-t {
  position: absolute;
  left: 20rpx;
  top: 15rpx;
  width: 30rpx;
  height: 6rpx;
  background-color: #000;
  transform: rotate(-45deg);
  border-radius: 5rpx;
}
.back-line-b {
  position: absolute;
  left: 20rpx;
  top: 32rpx;
  width: 30rpx;
  height: 6rpx;
  background-color: #000;
  transform: rotate(45deg);
  border-radius: 5rpx;
}

2.继续在components里面创建xr-ar-oceanWorld组件
在这里插入图片描述
index.js文件代码

Component({
  behaviors: [require('../common/share-behavior').default],//路径按照自己项目路径来
  miku: null,
  mikuTransform: null,
  mikuAnimator: null,
  animationRuning: false,
  isShow: false,
  properties: {
    //是否显示文字贴图默认不显示
    isShowDolphin: {
      type: false
    },
  },
  wxball: null,
  time1: null,
  time2: null,
  data: {
    loaded: false,
    arReady: false,
  },
  lifetimes: {
    async attached() {
      // console.log('data', this.data);
    }
  },
  methods: {
    handleReady({
      detail
    }) {
      const xrScene = this.scene = detail.value;
      const xrFrameSystem = wx.getXrFrameSystem();
    },
    handleAssetsProgress: function ({
      detail
    }) {
    },
    handleAssetsLoaded: function ({
      detail
    }) {
      // console.log('assets loaded', detail.value);
      this.setData({
        loaded: true
      });
    },
    handleTouchmiku: function() {
    //  console.log('miku TOUCH', this.animationRuning);
      // if (!this.animationRuning) {
      //   
      //   this.animationRuning = true;

      //   this.mikuAnimator.pauseToFrame('gltfAnimation', 1);
      //   this.mikuAnimator.pauseToFrame('gltfAnimation#0', 1);
        
      //   this.mikuAnimator.resume('gltfAnimation');
      //   this.mikuAnimator.resume('gltfAnimation#0');
      // }
    },
    handleAnimationStop: function() {
      console.log('animation Stop');
    },
    // 识别模型状态
    handleARTrackerState({detail}) {
      // 事件的值即为`ARTracker`实例
      const tracker = detail.value;
    
      // 获取当前状态和错误信息
      const {state, errorMessage} = tracker;
      // const video = this.scene.assets.getAsset('video-texture', 'hikari', 'white');
      console.log(state==2);

      if(state==2){
         console.log("状态识别成功", state)
        this.time1 = setTimeout(() => {
         this.setData({
           isShow: true
         })
        }, 1000)
        // this.time2 = setTimeout(() => {
        //   console.log("暂停动画")
        //   const animator1 = this.scene.getElementById('wxball-1').getComponent("animator");
        //   animator1.pause();
        //   const animator2 = this.scene.getElementById('wxball-2').getComponent("animator");
        //   animator2.pause();
        // }, 7000)
      }else{
        // clearTimeout(this.time1);
        // clearTimeout(this.time2);
        this.setData({
          isShow: false
        })
      }

    },
       // 识别海豚
       handleARTrackerState1({detail}) {
        // 事件的值即为`ARTracker`实例
        const tracker = detail.value;
      
        // 获取当前状态和错误信息
        const {state, errorMessage} = tracker;
        // const video = this.scene.assets.getAsset('video-texture', 'hikari', 'white');
        console.log(state==2);
  
        if(state==2){
           console.log("识别海豚", state);
            // this.triggerEvent('传递给父组件的自定义事件名称 newValue',传给父组件的数据 valueText)
          this.time1 = setTimeout(() => {
         this.triggerEvent('changeDolphin',{isShowDolphin:true})
           this.setData({
             isShow: true,
             isShowDolphin:true
           })
          }, 1000)
          // this.time2 = setTimeout(() => {
          //   console.log("暂停动画")
          //   const animator1 = this.scene.getElementById('wxball-1').getComponent("animator");
          //   animator1.pause();
          //   const animator2 = this.scene.getElementById('wxball-2').getComponent("animator");
          //   animator2.pause();
          // }, 7000)
        }else{
          this.triggerEvent('changeDolphin',{isShowDolphin:false})
          // clearTimeout(this.time1);
          // clearTimeout(this.time2);
          this.setData({
            isShow: false
          })
        }
  
      },
    handleARReady({detail}) {
      const xrFrameSystem = wx.getXrFrameSystem();
      const tracker = this.scene.getElementById('ar-tracker').getComponent(xrFrameSystem.ARTracker);
      // 初始状态
      const {state, errorMessage} = tracker;
      // 绑定事件
      tracker.el.event.add('ar-tracker-state', tracker => {
        const {state, errorMessage} = tracker;

      });
    },
     handleGLTFLoaded({detail}) {
      // console.log("进来了")
      // const el = detail.value.target;
      // const animator = el.getComponent("animator");
      // console.log("1111",animator)
      //  setTimeout(function(){
      //   console.log("暂停了")
      //   animator.pause();
      //  },3000)
      
  }
  }
})

index.json文件代码

{
  "component": true,
  "usingComponents": {
    "xr-demo-viewer": "../xr-demo-viewer/index"
  },
  "renderer": "xr-frame"
}

index.wxml

<xr-scene ar-system="modes:Marker;planeMode: 3" id="xr-scene" bind:ready="handleReady" bind:ar-ready="handleARReady" bind:log="handleLog">
  <xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoaded">
    <xr-asset-load type="gltf" asset-id="miku" src="要是别的模型"/>
    <xr-asset-load type="gltf" asset-id="miku2" src="要显示的模型glb格式"/>
  </xr-assets>
  <xr-env env-data="gz-haixinsha" />
  <xr-node>
    <!-- 识别图片 -->
    <xr-ar-tracker id="ar-tracker" mode="Marker" src="识别的图片" bind:ar-tracker-state="handleARTrackerState1">
      <xr-gltf id="wxball-1" position="0.2 0.7 -0.25" scale="0.025 0.025 0.025" rotation="-90 0 0" model="miku" anim-autoplay bind:gltf-loaded="handleGLTFLoaded" wx:if="{{isShow}}"></xr-gltf>
    </xr-ar-tracker>
    <!-- 识别图片 水母-->
    <xr-ar-tracker id="ar-tracker" mode="Marker" src="识别的图片" bind:ar-tracker-state="handleARTrackerState">
    <!-- 最新使用 0 -1 1  0.45 0.45 0.45-->
      <!-- <xr-gltf id="wxball-2"  position="0 -0.5 1" scale="0.45 0.45 0.45" rotation="-90 0 0" model="miku2" anim-autoplay bind:gltf-loaded="handleGLTFLoaded" wx:if="{{isShow}}"></xr-gltf> -->
      <xr-gltf id="wxball-2"  position="0 0 0.5" scale="0.3 0.3 0.3" rotation="-90 0 0" model="miku2" anim-autoplay bind:gltf-loaded="handleGLTFLoaded" wx:if="{{isShow}}"></xr-gltf>
    </xr-ar-tracker>
    <xr-camera
      id="camera" node-id="camera" position="1 1 1" clear-color="0.925 0.925 0.925 1"
      far="2000" background="ar" is-ar-camera
    ></xr-camera>
  </xr-node>
  <xr-node node-id="lights">
    <xr-light type="ambient" color="1 1 1" intensity="2" />
    <xr-light type="directional" rotation="90 60 0" color="1 1 1" intensity="1" />
  </xr-node>
</xr-scene>



3.pages文件夹里创建scene-ar-oceanWorld文件
在这里插入图片描述
index.js代码

var sceneReadyBehavior = require('../../behavior-scene/scene-ready');//路径按照自己项目路径来
Page({
    behaviors: [sceneReadyBehavior],
    data: {
      isShowDolphin:false,//默认不是海豚
        isShow: false,
        show: false,
        video: false,
        progressFlag: 0,
        loadingAni: false,
        isbegin: true,
        time1: null,
        time2: null,
        time3: null,
        rotation: {
            x:0,
            y: 0,
            z: 0,
        },
        op_n:0,
        meshCount: 0,
        loading: 0,
        barIsShow: true,
        endShow:false,
        timer:"",
        deflautWidth:0,
        musicbg:null
    },
    onUnload(){
      this.musicbg.stop();
      // 清除video定时器
      // clearTimeout(this.data.time3);
    },
    onLoad(options) {
      wx.setNavigationBarTitle({
        title: "潜入海洋的梦里"
        })
        let that = this;
        // 背景音乐
        this.musicbg = wx.createInnerAudioContext()
        this.musicbg.src ="背景音乐地址";
        this.musicbg.volume=0.6;
        this.musicbg.loop = true;
        this.musicbg.play();
        let index = 0;
        this.data.timer=setInterval(() => { //注意箭头函数!!
          index += 1;
          that.setData({
            deflautWidth: index
          })
          if (that.data.deflautWidth == 100) {
            clearInterval(this.data.timer);
          }
        }, 1000);
        
        setTimeout(res=>{
          that.setData({
            deflautWidth: 100
          })
        },3000)
      // 关闭主页按钮
      wx.hideHomeButton();
      
    },
    // 场景加载成功回调
    loadedInfo(){
    
    },
    //获取海豚状态
    changeDolphin(e){
      console.log('获取海豚状态',e.detail);
      this.setData({
        isShowDolphin:e.detail.isShowDolphin
      })
    },
    end() {
      console.log("1111")
    },
    // 获取微信头像
    handleReady: function ({detail}) {
      this.scene = detail.value;
      // 该接口已废弃,请授权后,采用 getUserInfo 代替。
      wx.getUserInfo()({
        desc: '获取头像',
        success: (res) => {
          console.log("微信授权", res);
          this.scene.assets.loadAsset({
            type: 'texture', assetId: 'avatar', src: res.userInfo.avatarUrl
          }).then(() => this.setData({avatarTextureId: 'avatar'}));
        }
      })
    },

    /**
     * 获取识别状态
     * Detected识别成功
     * Detecting未识别
     */
    handleARTrackerState({
        detail}) {
          console.log(detail,"识别");
        const {
            state,
            error
        } = detail;
        this.tracker = wx.getXrFrameSystem().ARTracker
        const {
            gesture
        } = this.tracker;
        this.gesture = gesture;
        let states = wx.getXrFrameSystem().EARTrackerState[state];
        if (states == "Detected") {
          // if (this.data.progressFlag == 0) {
            this.setData({
              progressFlag: 1
            })
             // 修改加载界面展示
            this.setData({
              show: true           
            })
            //识别成功
            this.data.time1 = setTimeout(() => {
              this.setData({
                show: false           
              })
            }, 1000)
            //识别成功
            // this.data.time2 = setTimeout(() => {
            //   this.setData({
            //     isShow: true,
            //   });
            //   // 在定时器回调中判断 isShow 的值
            //   if (this.data.isShow) {
            //     this.data.time3 = setTimeout(() => {
            //       console.log("进入if");
            //       this.setData({
            //         video: true,
            //       });
            //       // 关闭音乐
            //       this.musicbg.stop();
            //     }, 4500);
            //   }
            // }, 10000);
            
          // } else{
          //   this.setData({
          //     show: false           
          //   })
          // }
        } else {
          //识别失败
          console.log("识别失败", states);
          this.setData({
            show: false,
            // isShow:false,
            // video: false
          });
          clearTimeout(this.data.time1);
          clearTimeout(this.data.time2);
          
        }
    },





    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady() {

    },

    onShow() {
        /**
         * 设置页面常亮
         */
        wx.setKeepScreenOn({
            keepScreenOn: true,
            fail() {
                //如果失败 再进行调用
                wx.setKeepScreenOn({
                    keepScreenOn: true
                });
            }
        });
    },

    onHide() {
      this.musicbg.stop();
    },
    
    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh() {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom() {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage() {

    }
})

index.json代码

{
  "usingComponents": {
    "xr-demo-viewer": "../../../components/xr-demo-viewer/index",//路径按照自己项目路径来
    "xr-ar-oceanWorld": "../../../components/xr-ar-oceanWorld/index"//路径按照自己项目路径来
  },
  "disableScroll": true
}

index.wxml文件代码

<xr-demo-viewer>
  <xr-ar-oceanWorld
  isShowDolphin="{{isShowDolphin}}"
  bindchangeDolphin="changeDolphin"
    disable-scroll
    id="main-frame"
    width="{{renderWidth}}"
    height="{{renderHeight}}"
    style="width:{{width}}px;height:{{height}}px;top:{{top}}px;left:{{left}}px;display:block;"
    bind:arTrackerState="handleARTrackerState"
  />
</xr-demo-viewer>

  <view class="faceMask" style="width: 100vw; height: 100vh;background-repeat: no-repeat;background-size: cover;background-position:center;z-index: auto;" wx:if="{{show}}">
    <view class="head1">
        <view style="display: flex;align-items: center;justify-content: center;height: 100vh;box-sizing: border-box;padding-bottom: 18vh;">
          <view style="width: 400rpx;">
            <progress percent="100" color="#3787BC"  stroke-width="18" active duration="10" />
          </view>
        </view>
    </view>
  </view>
  <!-- 文字贴图 -->
  <!-- <view  wx:if="{{isShowDolphin}}" style="color: aqua;font-size: 40RPX;text-align: center;width: 100VW;height: 100vh;position: relative;z-index: 9999999;">
  <view style="position: absolute;bottom: 66vw;left: 0;width: 100vw;">
    <image src="../../../assets/image/logo.png" mode="widthFix" style="width: 100%;"></image>
  </view>
  </view> -->

index.wxss代码

page{width: 100%;height: 100%;}
.mask_bg{width: 100%;height: 100%; background: rgba(0,0,0,0.3); position: absolute; top:0; left: 0; z-index: 10;}
.mask_Img{width: 100%; height: 100%;}
.mask_Box{width: 100%; position: relative; }
.rote{width: 100%; height: 100%;position: absolute; top:0;left: 0;}
.rote image{width: 95%;animation:rotate_music 5s linear infinite; transform-origin: 50% 50%;}
@keyframes rotate_music{0%{transform: rotate(0deg);} 50%{transform: rotate(180deg);} 100%{transform: rotate(360deg);}}
.Detecting{position: absolute;top:0; left: 0; width: 100%; height: 100%; overflow: hidden; border-radius: 100%;}
.Detecting image{animation:d1 4s linear infinite;}
@keyframes d1{0%,100%{transform: translateY(0);} 50%{transform: translateY(65vw);}}
.ar3d{width: 100%; height: 100%; position: absolute;top:0;left: 0; z-index: 10; display: none; }
.ar3d_box{width: 100%; height:90%;perspective:1px; perspective-origin:center center;}
.ar3d_box text{font-size: 1em;animation:tz 5s linear infinite; color:#fff;}
@keyframes tz{0%{transform: translateZ(-3px);} 100%{transform: translateZ(1px);}}
.loading{width: 100%; text-align: center; margin-top: 20%;}
.loading .box{width: 60%; margin: 0 auto; position: relative;}
.loading .bar{width: 100%; position: absolute; bottom: 2%; left: 0; height:40%;}
.loading .bar_loading{width: 100%; height: 100%;  }
.tips{width: 100%; text-align: center; margin-top: 5%;}
.tips image{width: 70%;}
.EndBox{position: absolute;top:0; left: 0; z-index: 2; width: 100%;height: 100%;}
.EndBox .box{width: 100%; height: 100%; background: url(https://cyvideo.i-oranges.com/ar/cdxg/index/ai1.gif) center no-repeat; background-size:cover}

.faceMask{width: 100%; height: 100%;position: absolute;top:0;left: 0; z-index: 999999;} 
/* .faceMask .head1{position: absolute;top:0; left: 0; width: 20%;} */
.faceMask .bottom1{position: absolute;bottom:0; left: 0; width: 100%;}
.faceMask .bottom1 image{vertical-align: middle;}
.faceMask .tips{position: absolute; bottom: 5%; width: 100%;}
.faceMask .tips .box{width: 45%; position: relative; margin: 0 auto;}
.faceMask .tips .close{position: absolute; width: 20%; right: -7%; top:-30%;}

4.在components组件里面创建common文件share-behavior.js
在这里插入图片描述
share-behavior.js代码

export default Behavior({
  created: function () {
    this.checkInitShare();
  },
  methods: {
    checkInitShare() {
      wx.xrScene = undefined;

      if (!this.scene) {
        setTimeout(() => {
          this.checkInitShare()
        }, 100);
        return;
      }

      if (this.scene.ar) {
        if (this.scene.ar.ready) {
          this.initARTrackerState(this.scene);    
        } else { 
          this.scene.event.add('ar-ready', () => this.initARTrackerState(this.scene));
        }
      }

      if (!this.scene.share.supported) {
        console.warn('Not support xr-frame share system now!');
        return;
      }

      this.sharing = false;
      wx.xrScene = this.scene;
    },
    initARTrackerState(scene) {
      const xrFrameSystem = wx.getXrFrameSystem();
      scene.dfs(() => {}, undefined, true, el => {
        const comp = el.getComponent(xrFrameSystem.ARTracker);
        if (comp) {
          if (typeof comp.state === 'number') {
            this.triggerEvent('arTrackerState', {state: comp.state, error: comp.errorMessage});
            el.event.add('ar-tracker-state', tracker => {
              this.triggerEvent('arTrackerState', {state: tracker.state, error: tracker.errorMessage});
            });
          }
          return true;
        }
      });
    }
  }
})

4.在pages中创建behavior-scene项目
在这里插入图片描述
scene-ready.js文件代码

module.exports = Behavior({
  behaviors: [],
  properties: {
  },
  data: {
    left: 0,
    top: 0,
    width: 0,
    height: 0,
    renderWidth: 0,
    renderHeight: 0,
    windowHeight: 1000,
    heightScale: 1,
    showBackBtn: false,
    activeValues: [1],
    arTrackerShow: false,
    arTrackerState: 'Init',
    arTrackerError: ''
  },
  attached: function(){},
  ready() {
    const info = wx.getSystemInfoSync();
    const width = info.windowWidth;
    const windowHeight = info.windowHeight;
    const height = windowHeight * this.data.heightScale;
    const dpi = info.pixelRatio;
    this.setData({
      width,
      height,
      renderWidth: width * dpi,
      renderHeight: height * dpi,
      windowHeight
    });
  },
  methods: {
    onLoad(options) {
      wx.reportEvent("xr_frame", {
        "xr_page_path": options.path
      });
    },
    // onShareAppMessage() {
    //   try {
    //     if (wx.xrScene) {
    //       const buffer = wx.xrScene.share.captureToArrayBuffer({quality: 0.5});
    //       const fp = `${wx.env.USER_DATA_PATH}/xr-frame-share.jpg`;
    //       wx.getFileSystemManager().writeFileSync(fp, buffer, 'binary');
    //       return {
    //         title: this.getTitle(),
    //         imageUrl: fp
    //       };
    //     }
    //   } catch (e) {
    //     return {
    //       title: this.getTitle()
    //     };
    //   }
    // },
    // onShareTimeline() {
    //   try {
    //     if (wx.xrScene) {
    //       const buffer = wx.xrScene.share.captureToArrayBuffer({quality: 0.5});
    //       const fp = `${wx.env.USER_DATA_PATH}/xr-frame-share.jpg`;
    //       wx.getFileSystemManager().writeFileSync(fp, buffer, 'binary');
    //       return {
    //         title: this.getTitle(),
    //         imageUrl: fp
    //       };
    //     }
    //   } catch (e) {
    //     return {
    //       title: this.getTitle()
    //     }
    //   }
    // },
    getTitle() {
      return wx.xrTitle ? `${wx.xrTitle}` : 'AR';
    },
    handleARTrackerState({detail}) {
      const {state, error} = detail;
      this.setData({
        arTrackerShow: true,
        arTrackerState: wx.getXrFrameSystem().EARTrackerState[state],
        arTrackerError: error
      });

    }
  }
})

utils.js代码

var handleDecodedXML = function(decodedXml) {
  let rerurnXml = '';

  const blockArr = decodedXml.split('&lt;');

  for (let i = 0; i < blockArr.length; i++) {
    let blockStr = blockArr[i];
    let handleBlockStr = '';
    let returnBlockStr = '';

    const sliceBlockStr = blockStr.split(' ');

    for(let j = 0; j < sliceBlockStr.length; j++) {
      const subBlockStr = sliceBlockStr[j];
      
      const eIndex = subBlockStr.indexOf('=');
      if (eIndex !== -1) {
        handleBlockStr += ' <span class="attr-name">' + subBlockStr.slice(0, eIndex) +'</span>' + subBlockStr.slice(eIndex);
      } else {
        handleBlockStr += subBlockStr;
      }
    }
    // console.log(sliceBlockStr);

    const blockEndIndexB = handleBlockStr.indexOf(' ');
    const blockEndIndexR = handleBlockStr.indexOf('&gt;');
    // Handle XMLTag
    if (blockEndIndexB === -1 && blockEndIndexR === -1) {
      continue;
    }
    const endBlockFlag = handleBlockStr[0] === '/';

    if (blockEndIndexR !== -1) {
      handleBlockStr += '<br>'
    }
    if (blockEndIndexR < blockEndIndexB) {
      returnBlockStr = '&lt;' + (endBlockFlag ? '/' : '') + '<span class="block-name">' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexR) + '</span>' + handleBlockStr.slice(blockEndIndexR);
    } else if (blockEndIndexB !== -1) {
      returnBlockStr = '&lt;' + (endBlockFlag ? '/' : '') +'<span class="block-name">' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexB) + '</span>' + handleBlockStr.slice(blockEndIndexB);
    } else if (blockEndIndexR !== -1) {
      returnBlockStr = '&lt;' + (endBlockFlag ? '/' : '') + '<span class="block-name">' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexR) + '</span>' + handleBlockStr.slice(blockEndIndexR);
    }
    rerurnXml += returnBlockStr;
  }
  return rerurnXml;
}

var escapeMarkup = function(dangerousInput) {
  const dangerousString = String(dangerousInput);
  const matchHtmlRegExp = /["'&<>]/;
  const match = matchHtmlRegExp.exec(dangerousString);
  if (!match) {
    return dangerousInput;
  }

  const encodedSymbolMap = {
    '"': '&quot;',
    '\'': '&#39;',
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;'
  };
  const dangerousCharacters = dangerousString.split('');
  const safeCharacters = dangerousCharacters.map(function (character) {
    return encodedSymbolMap[character] || character;
  });
  const safeString = safeCharacters.join('');
  return safeString;
}


module.exports = {
  handleDecodedXML,
  escapeMarkup
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1360397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

呼叫 Mac 用户 | Navicat Premium 原生支持在搭载 Apple Silicon 芯片的电脑上使用

作为桌面端数据库管理开发软件&#xff0c;Navicat Premium 与 Navicat for MongoDB 16.3 (或更高版本) 已原生支持搭载 Apple Silicon 芯片的 Mac 电脑上使用。这是一次重要的技术改进&#xff0c;通过原生技术将大幅提升 Mac 用户在使用 Navicat 过程中的响应速度、流畅性以及…

[C#]使用OpenCvSharp实现二维码图像增强超分辨率

【官方框架地址】 github.com/shimat/opencvsharp 【算法介绍】 借助于opencv自带sr.prototxt和sr.caffemodel实现对二维码图像增强 【效果展示】 【实现部分代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin…

C++结合OpenCV:图像的基本表示方法

1.二值图像 二值图像是指仅仅包含黑色和白色两种颜色的图像。在计算机中&#xff0c;通过一个栅格状排列的数据集&#xff08;矩阵&#xff09;来表示和处理图像。例如&#xff0c;图1是一个字母A的图像&#xff0c;计算机在处理该图像时&#xff0c;会首先将其划分为一个个的小…

C# OpenCvSharp DNN FreeYOLO 人脸检测

目录 效果 模型信息 项目 代码 下载 C# OpenCvSharp DNN FreeYOLO 人脸检测 效果 模型信息 Inputs ------------------------- name&#xff1a;input tensor&#xff1a;Float[1, 3, 192, 320] --------------------------------------------------------------- Outp…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑多元不确定性和备用需求的微电网双层鲁棒容量规划》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题涉及微电网&#xff08;Microgrid&#xff09;的双层鲁棒容量规划&#xff0c;考虑了多元不确定性和备用需求。让我们逐步解读这个标题&#xf…

【AI视野·今日NLP 自然语言处理论文速览 第六十六期】Tue, 31 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 31 Oct 2023 (showing first 100 of 141 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Eval4NLP 2023 Shared Task on Prompting Large Language Models a…

箭头函数 - JavaScript的新宠儿

&#x1f4e2; 鸿蒙专栏&#xff1a;想学鸿蒙的&#xff0c;冲 &#x1f4e2; C语言专栏&#xff1a;想学C语言的&#xff0c;冲 &#x1f4e2; VUE专栏&#xff1a;想学VUE的&#xff0c;冲这里 &#x1f4e2; CSS专栏&#xff1a;想学CSS的&#xff0c;冲这里 &#x1f4…

C++——STL标准模板库——容器详解——stack+queue

一、基本概念 &#xff08;一&#xff09;stack&#xff08;栈或堆栈&#xff09; 一种只允许同一端进出的线性数据结构&#xff0c;数据先进后出。基本模型类似于瓶子。 &#xff08;二&#xff09;queue&#xff08;队列&#xff09; 一种只允许一端进、另一端出的线性数…

UE5.1_UMG序列帧动画制作

UE5.1_UMG序列帧动画制作 UMG序列帧动画制作相对比较简单&#xff0c;不像视频帧需要创建媒体播放器那么复杂&#xff0c;以下简要说明&#xff1a; 1. 事件函数 2. 准备序列帧装入数组 3. 构造调用事件函数 4. 预览 序列帧UMG0105 5. 完成&#xff01;按需配置即可。

本地引入Element UI后导致图标显示异常

引入方式 npm 安装 推荐使用 npm 的方式安装&#xff0c;它能更好地和 webpack 打包工具配合使用。 npm i element-ui -SCDN 目前可以通过 unpkg.com/element-ui 获取到最新版本的资源&#xff0c;在页面上引入 js 和 css 文件即可开始使用。 <!-- 引入样式 --> <…

面试题-DAG 有向无环图

有向无环图用于解决前后依赖问题&#xff0c;在Apollo中用于各个组件的依赖管理。 在算法面试中&#xff0c;有很多相关题目 比如排课问题&#xff0c;有先修课比如启动问题&#xff0c;需要先启动1&#xff0c;才能启动2 概念 顶点&#xff1a; 图中的一个点&#xff0c;比…

scratch绘制小正方形 2023年12月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析

目录 scratch绘制小正方形 一、题目要求 1、准备工作 2、功能实现 二、案例分析

揭开 JavaScript 作用域的神秘面纱(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

第11章 GUI Page462~476 步骤二十三 步骤二十四 Undo/Redo ②“添加操作”支持“Undo/Redo”

工程二 1.为AddAction类添加Undo() Redo() GetName()成员函数 2.实现AddAction类的Undo() Redo()函数 3.运行效果&#xff0c;但是日志窗口没有记录 原因&#xff1a;AddAction(EditAction* newAction)函数没有实现&#xff0c;另外参数是EditAction类型 所以我们还需要在基…

C# .Net学习笔记—— 异步和多线程(await/async)

一、介绍 1、控制台测试await/async 2、C# 5.0 .Net framework4.5 CLR4.0 以后才有&#xff0c;本身是一种语法糖 二、基本测试 1、不加await测试。 private async static Task TestAsync() {Log.Info($"当前主线程id{Thread.CurrentThread.ManagedThreadId}"…

简易视频播放器(案例)

介绍 本篇Codelab使用ArkTS语言实现视频播放器&#xff0c;主要包括主界面和视频播放界面&#xff0c;我们将一起完成以下功能&#xff1a; 主界面顶部使用Swiper组件实现视频海报轮播。主界面下方使用List组件实现视频列表。播放界面使用Video组件实现视频播放。在不使用视频组…

在Uniapp中使用Echarts创建可视化图表

在uniapp中可以引入echarts创建数据可视化图表。 1. 安装Echarts 使用npm安装echarts插件&#xff0c;命令如下&#xff1a; npm install echarts --save2. 引入Eharts 在需要使用Echarts的页面引入&#xff1a; import *as echarts from echarts3. 创建实例 创建画布元素…

基于单片机的农田灌溉系统(论文+源码)

1.系统设计 本系统主要实现如下目标&#xff1a; 1&#xff0e;可以实时监测土壤湿度&#xff1b; 2&#xff0e;土壤湿度太低时&#xff0c;进行浇水操作&#xff1b; 3&#xff0e;可以按键设置湿度的触发阈值&#xff1b; 4. 可以实现远程操控 5&#xff0e;可以实现手…

基于 ESP32-C3 开启 Flash 加密和安全启动并进行 OTA 测试

软件&#xff1a; esp-idf v5.1.2 硬件&#xff1a; ESP32-C3 board 1. 首先&#xff0c;准备一个明文固件 hello-world.bin 基于 esp-idf-v5.1.2\examples\get-started\hello_world 例程&#xff0c;使用如下指令&#xff0c;直接编译&#xff0c;获取明文固件 hello-worl…

【软考中级-软件设计师】day1:CPU、数据的表示、校验码

考点分布目录 中央处理单元CPU 练习题 数据的表示 二进制转十进制 练习题 十进制转二进制 练习题 原码 练习题 反码 练习题 补码 练习题 练习题 移码 浮点数 练习题 奇偶校验 练习题 校验码 模2除法 循环冗余校验CRC 练习题 练习题 练习题 奇偶校验码 只…