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

效果

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
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

引导过程和服务

宏内核(monolithic kernel)&#xff1a;又称单内核和强内核&#xff0c;Unix&#xff0c;Linux把所有系统服务都放到内核里&#xff0c;所有功能集成于同一个程序&#xff0c;分层实现不同功能&#xff0c;系统庞大复杂&#xff0c;Linux其实在单内核内核实现了模块化&#xff…

汽车电子学习总结

国内的主要有比亚迪、联合汽车电子&#xff08;联电&#xff09;、麦格米特、上海电驱动&#xff1b;国外的主要有欧美系的博世、麦格纳、大陆、博格华纳&#xff1b;日系的电装、电产等公司。

【Android Studio】在单独的窗口中启动模拟器

参考&#xff1a;https://developer.android.com/studio/run/emulator-launch-separate-window?hlzh-cn 默认情况下&#xff0c;Android 模拟器会在 Android Studio 中运行。这样&#xff0c;您就可以高效地使用屏幕空间&#xff0c;使用热键在模拟器和编辑器窗口之间快速导航…

华为交换机基于mac地址划分VLAN

SW1配置 vlan 10mac-vlan mac-address 5489-98c3-5611 #pc1 mac地址 mac-vlan mac-address 5489-98c3-5622 #pc2 mac地址 interface GigabitEthernet0/0/1undo port hybrid vlan 1 #禁用交换机默认的vlan 1&#xff0c;避免产生干扰port hybrid untagged vlan 10mac-vlan enab…

【Java】RuoYi-Vue-Plus 多数据源整合TDengine时序数据库——服务端自动建库建表

目录 环境准备整合TDengine 数据源1. 添加驱动依赖2. 添加数据源配置3. 添加Mapper4. 添加建表sql脚本5. Controller 测试效果 环境准备 RuoYi-Vue-Plus v5.1.2JDK17Maven 3.6.3Redis 5.XMySQL 5.7TDengine 2.6.0.34 客户端 整合TDengine 数据源 1. 添加驱动依赖 注意&…

【AWS系列】巧用 G5g 畅游Android流媒体游戏

序言 Amazon EC2 G5g 实例由 AWS Graviton2 处理器提供支持&#xff0c;并配备 NVIDIA T4G Tensor Core GPU&#xff0c;可为 Android 游戏流媒体等图形工作负载提供 Amazon EC2 中最佳的性价比。它们是第一个具有 GPU 加速功能的基于 Arm 的实例。 借助 G5g 实例&#xff0c;游…

亚信安慧AntDB数据库:企业核心业务系统数据库升级改造的可靠之选

在近期召开的“2023年国有企业应用场景发布会”上&#xff0c;亚信安慧公司的核心数据库产品AntDB闪耀登场&#xff0c;技术总监北陌先生针对企业核心业务系统数据库升级改造的关键议题发表了深度分享。他从研发、工程实施和运维管理三个维度细致剖析了当前企业在进行数据库升级…

OpenCASCADE MFC例子

OpenCASCADE MFC例子 说明 一直对OpenCASCADE一直都比较感兴趣&#xff0c;这个例子是我参考这位大神C幼儿园中班小朋友的专栏做出来的OpenCASCADE_C幼儿园中班小朋友的博客-CSDN博客 不过我用的是vcpkg的方式安装OpenCASCADE&#xff0c;这个需要注意一下&#xff0c;可能需…

智慧机房建设浪潮:2024年动环监控系统厂家排名出炉

近几年来&#xff0c;伴随着信息化技术的快速发展&#xff0c;老旧的传统机房在设备性能、网络安全、数据统计等各方面都已经不再能完全满足使用需求&#xff0c;国内多个机房兴起了轰轰烈烈的智慧机房建设浪潮。不同于传统机房只能依赖人工24小时值守&#xff0c;智慧机房凭借…

数据库之存储引擎

1. 存储引擎的概念 存储引擎是MYSQL数据库的组件&#xff0c;负责执行时间的数据I/O操作&#xff08;数据的存储和提取&#xff09;&#xff0c;工作在文件系统之上&#xff0c;数据库的数据会先传到存储引擎&#xff0c;再按照存储引擎的存储格式保存到文件系统。 &#xff…

Spring学习 Spring IOC

创建工程&#xff1a; 2.1.程序的耦合 耦合&#xff1a;耦合指的就是对象之间的依赖关系。对象之间的耦合越高&#xff0c;维护成本越高。 案例&#xff1a;没有引入IOC容器时系统的Web层、业务层、持久层存在耦合 /*** 持久层实现类*/ public class UserDaoImpl implements U…

判断完全数-第11届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第27讲。 判断完全数&#…

如何理解Nacos的CP和AP架构模型?

Nacos是阿里巴巴开源的注册中心和配置中心&#xff0c;它既可以替应用服务管理服务相关的元数据&#xff0c;也可以管理服务相关的配置信息。 Nacos既支持单机部署&#xff0c;也支持集群部署&#xff0c;为了保证数据的一致性&#xff0c;在集群模式下&#xff0c;Nacos既支持…

CAD加密软件哪个好?CAD图纸加密软件哪个好(图纸加密软件哪个最好用)

图纸防泄密软件现在市场上是很多的&#xff0c;但是普遍采用的图纸防泄密软件技术是采用透明加密的技术&#xff0c;当企业采用透明加密技术对的图纸文件进行安全防护时&#xff0c;也是最安全的最稳定的技术。 现在常用的使用透明加密技术&#xff0c;对企业图纸防泄密的方法…

人工智能_机器学习092_使用三维瑞士卷数据_利用分层聚类算法进行瑞士卷数据三维聚类---人工智能工作笔记0132

然后我们使用分层聚类算法来对我们导入的瑞士卷数据进行聚类 agg =AgglomerativeClustering(n_clusters = 6,linkage = ward) 可以看到这里我们使用的,聚类距离计算用的是,ward这种,最小化簇内方差的形式,l进行聚类对吧 可以看到这个linkage参数有好几个选择对吧,是之前我们讲过…

复现PointNet(分割网络):Windows + PyTorch+代码

一、平台 Windows 10 GPU RTX 3090 CUDA 11.1 cudnn 8.9.6 Python 3.9 Torch 1.9.1cu111 所用的原始代码&#xff1a;https://github.com/fxia22/pointnet.pytorch​​​​​​​ 二、数据 shapenetcore_partanno_segmentation_benchmark_v0 三、代码 分享给有需要的…

【c语言】指针小结

一、指针是什么&#xff1f; 可以通过运算符&来取得变量实际保存的 起始地址 。 &#xff08;这个地址是虚拟地址&#xff0c;并不是真正物理内存上的地址。&#xff09; 数据类型 *标识符 &变量; int *pa &a; int *pa NULL; (NULL表示地址为0的内存空间&a…

金和OA JC6 ntko-upload 任意文件上传漏洞

产品介绍 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 漏洞概述 金和 OA JC6 ntko-upload接口处存在任意文件上传漏洞&#xff0c;攻击者可以通过构造特殊请求包上…

使用Go语言的HTTP客户端库进行API调用

随着微服务架构和RESTful API的普及&#xff0c;API调用成为了日常开发中的常见任务。Go语言提供了多种工具和库来帮助开发者轻松地与API进行交互。本文将介绍如何使用Go语言的HTTP客户端库进行API调用。 在Go语言中&#xff0c;标准库中的net/http包提供了基本的HTTP客户端功…

【物联网】手把手完整实现STM32+ESP8266+MQTT+阿里云+APP应用——第3节-云产品流转配置

&#x1f31f;博主领域&#xff1a;嵌入式领域&人工智能&软件开发 本节目标&#xff1a;本节目标是进行云产品流转配置为后面实际的手机APP的接入做铺垫。云产品流转配置的目的是为了后面能够让后面实际做出来的手机APP可以控制STM32/MCU&#xff0c;STM32/MCU可以将数…