前言

Tracking.js 是一个独立的JavaScript库(不依赖于任何框架),用于跟踪从相机实时收到的数据。

跟踪的数据既可以是颜色,也可以是人,

也就是说我们可以通过检测到某特定颜色,或者检测一个人体/脸的出现与移动,来触发JavaScript 事件。

它是非常易于使用的API,具有数个方法和事件(足够使用了)。

还有一个我觉得不错的功能就是,截取摄像头的图像,对于一些网站用这个功能来设置用户头像也是个很炫的功能。

安装

yarn add tracking
yarn add @types/tracking

使用教程

例子是vue3+ts+less

安装并引入

//@ts-nocheck

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import "tracking";
import "tracking/build/data/face";
import { Notify } from 'vant'; function getUserMedia(constrains, success, error) {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
//最新标准API
Notify({ type: 'success', message: '支持最新标准API' });
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
Notify({ type: 'success', message: '支持webkit内核浏览器' });
//webkit内核浏览器
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.mozGetUserMedia) {
Notify({ type: 'success', message: '支持Firefox浏览器' });
//Firefox浏览器
navagator.mozGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.getUserMedia) {
Notify({ type: 'success', message: '支持旧版API' });
//旧版API
navigator.getUserMedia(constrains).then(success).catch(error);
} else {
Notify('浏览器不支持getUserMedia');
}
} // 要重写initUserMedia_ 方法,因为chrome的底层api已做调整
window.tracking.initUserMedia_ = function (element, opt_options) {
const options = {
video: true,
audio: !!(opt_options && opt_options.audio)
};
getUserMedia(options, function (stream) {
try {
element.srcObject = stream;
} catch (err) {
element.src = window.URL.createObjectURL(stream);
}
}, function (e) {
Notify(e.message);
}
);
}; // 重写视频捕获方法,因为不能停止 stop无效的bug
window.tracking.trackVideo_ = function (element, tracker) {
console.log('trackVideo_');
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var width;
var height; var resizeCanvas_ = function () {
width = element.offsetWidth;
height = element.offsetHeight;
canvas.width = width;
canvas.height = height;
};
resizeCanvas_();
element.addEventListener('resize', resizeCanvas_); var requestId;
var stopped = false;
var requestAnimationFrame_ = function () {
requestId = window.requestAnimationFrame(function () {
if (element.readyState === element.HAVE_ENOUGH_DATA) {
try {
// Firefox v~30.0 gets confused with the video readyState firing an
// erroneous HAVE_ENOUGH_DATA just before HAVE_CURRENT_DATA state,
// hence keep trying to read it until resolved.
context.drawImage(element, 0, 0, width, height);
} catch (err) { }
tracking.trackCanvasInternal_(canvas, tracker);
}
if (stopped !== true) {
requestAnimationFrame_();
}
});
};
var task = new tracking.TrackerTask(tracker);
task.on('stop', function () {
stopped = true;
window.cancelAnimationFrame(requestId);
});
task.on('run', function () {
stopped = false;
requestAnimationFrame_();
});
return task.run();
}; createApp(App).use(router).mount('#app')
<template>
<div class="wrapp">
<video id="myVideo" width="800" height="500" preload="preload" autoplay loop muted src="/other/video.mp4" />
<canvas ref="myCanvas" class="myCanvas" width="800" height="500"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'; // 标识用的画布
const myCanvas = ref<HTMLCanvasElement | null>(null); // 实例颜色检查器
const myTracker = new tracking.ColorTracker(['yellow']); // 监听颜色检查器
myTracker.on('track', (event: tracking.TrackEvent) => {
const context = myCanvas.value?.getContext('2d') as CanvasRenderingContext2D;
if (myCanvas.value) {
context.clearRect(0, 0, myCanvas.value.width, myCanvas.value.height);
}
if (event.data.length === 0) {
console.log('没有捕获到内容');
} else {
event.data.forEach((rect: tracking.TrackRect) => {
const { x, y, width, height, color = 'red' } = rect;
context.strokeStyle = color;
context.strokeRect(x, y, width, height);
context.font = '11px Helvetica';
context.fillStyle = '#fff';
context.fillText(`x:${x}px`, x + width + 5, y + 11);
context.fillText(`y:${y}px`, x + width + 5, y + 22);
});
}
}); onMounted(() => {
// 触发颜色检查器
tracking.track('#myVideo', myTracker);
});
</script>
<style lang="less" scoped>
.wrapp {
position: relative;
.myCanvas {
position: absolute;
top: 0;
left: 0;
}
}
</style>

效果

补充

如果需要摄像头实时捕获,则出触发调用,option配置参数 这样即可

onMounted(() => {
// 触发颜色检查器
tracking.track('#myVideo', myTracker, { camera: true });
});

一、trackingjs初体验-颜色捕获 vue3的更多相关文章

  1. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  2. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  3. 百度EChart3初体验

    由于项目需要在首页搞一个订单数量的走势图,经过多方查找,体验,感觉ECharts不错,封装的很细,我们只需要看自己需要那种类型的图表,搞定好自己的json数据就OK.至于说如何体现出来,官网的教程很详 ...

  4. Java8初体验(二)Stream语法详解

    感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 上篇文章Java8初体验(一)lambda表达式语法比 较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例 ...

  5. iOS AR技术初体验,使用EasyAR示例程序的小白指南

    QQ前两天的传递火炬,是我第一次直接接触到AR.(虽然之前听同事说过,因为他喜欢玩游戏,PS.3DS等等都玩过,这个技术最开始就是从这里出现的).所以感觉很有趣,就想自己也试着搞一下玩玩...下面是我 ...

  6. Microsoft IoT Starter Kit 开发初体验-反馈控制与数据存储

    在上一篇文章<Microsoft IoT Starter Kit 开发初体验>中,讲述了微软中国发布的Microsoft IoT Starter Kit所包含的硬件介绍.开发环境搭建.硬件 ...

  7. PHP初体验

    PHP初体验 提笔写初体验总不知道从何说起,直接聊PHP中的函数.PHP网络技术.数据库操作.PHP模板等感觉又不是初体验.最后还是决定从PHP的面向对象.PHP的魔术方法.PHP的反射.PHP中的异 ...

  8. Swift与C++混编 OpenCV初体验 图片打码~

    OpenCV初体验,给图片打码 提到OpenCV,相信大多数人都听说过,应用领域非常广泛,使用C++开发,天生具有跨平台的优势,我们学习一次,就可以在各个平台使用,这个还是很具有诱惑力的.本文主要记录 ...

  9. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

  10. SASS初体验

    SASS初体验 标签(空格分隔): sass scss css 1. 编译环境 需要安装Ruby,之后需要打开Start Command Prompt with Ruby运行 gem install ...

随机推荐

  1. AIR724UG上电后引脚的默认电平

    使用AIR724UG的引脚作为继电器的控制引脚时,由于上电时引脚的电平有的高,有的低. 在某些场合我们希望GPIO上电默认是低电平,所以我将常用引脚中可用的引脚标注了出来.

  2. Google发布A2A开源协议:“MCP+A2A”成未来标配?

    就在刚刚Google Cloud Next 25大会上,谷歌重磅开源Agent2Agent(A2A)协议,这项被类比为"AI界的HTTP协议"的技术标准,彻底打破了智能体间的信息孤 ...

  3. MCP应用docker部署,docker-compose部署

    一.概述 前面几篇文章,MCP应用直接用的python3 server.py运行的,如果服务器重启,进程就会关掉,很不方便. 所以需要使用docker部署,实现开机自启动. 二.docker部署 my ...

  4. 学习nodejs的一点笔记

    >>1.模块:一个文件即为一个模块 1)global可以声明全局变量 (跨模块) 例如:global a = 100; console.log(global.a);   //输出100 2 ...

  5. 前端自动打包工具webpack的安装和使用

    一.准备 要使用webpack工具,最好了解一些基础的文件目录操作的命令行, win all里的一些常用的命令行 http://blog.csdn.net/qq_36110571/article/de ...

  6. 我们离Agent终极形态又近了一步:全球首个支持谷歌A2A(Agent-to-Agent)协议的智能体注册网站上线Product Hunt,未来智能体协作网络

    AI 的终点,不是更强大的对话,而是一个真正协作的智能体社会. 这种形态已经在悄然出现. 全球首个支持 Google A2A(Agent-to-Agent)协议 的智能体注册与协作平台同步上线Prod ...

  7. 题解:CF361B Levko and Permutation

    前置芝士--最大公约数 - OI Wiki 题目其实很简单,我们可以知道一些最大公约数的性质: 有一个数 xxx,则: gcd⁡(x,x−1)=1gcd⁡(1,x)=1\gcd(x,x-1)=1 \\ ...

  8. 解决MySQL数据库中1045错误[1045 Access denied for user 'root'@'localhost' (using password:YES)]

    数据库连接异常 1045 Access denied for user 'root'@'localhost' (using password:YES) 这种问题的本质是用户密码出现错误 解决方案 1. ...

  9. C#基础——超级方便的ExpandoObject类别

    这东西是.NET Framework 4.5 的新东西..发现这个,大概就跟发现新大陆一样的兴奋,让我再次赞叹Anders Hejlsberg 之神.. 这边有MSDN : http://msdn.m ...

  10. LightGBM算法原理及Python实现

    一.概述   LightGBM 由微软公司开发,是基于梯度提升框架的高效机器学习算法,属于集成学习中提升树家族的一员.它以决策树为基学习器,通过迭代地训练一系列决策树,不断纠正前一棵树的预测误差,逐步 ...