96编辑器旗下产品
找图
终身
ID:0
到期时间:永久
退出登录
您的位置:首页 > 百科管理 > 详情

canvas在线画图-vuepc电脑可以获取设备吗

原创:找图网 2023-04-11 07:14:03
  • canvas绘制箭头路径效果

  • 前几天有很多人问到了如何绘制高德地图那样的

    导航箭头线

    效果,当时想了想并不难就先用canvas 做了,然后集成到了mapbox 上。 在线体验地址 ,迁移到其他map lib 也只需要应用相应的

    地理转屏幕坐标

    函数。

    在canvas 的应用中我们经常会遇到各种线样式的绘制,比如虚线,渐变线,带pattern 线(箭头,铁轨图标等),或者虚线与pattern 的动画效果。如下图所示,总结下实现方法。

    比如 ([10, 5]),就可以画出上图的虚线效果。发挥想象可以做出更多奇特效果。比如让虚线动起来,有走马灯的感觉。。

    通过 createLinearGradient 函数创建渐变,然后设定其渐变色段, 赋值给strokeStyle,渐变效果如开头图所示

    有个问题就是如果需要

    渐变方向符合线条走向

    ,这是常见需求,只需要提前算下每条线的范围和方向,创建对应的LinearGradient 即可,其实类似于下面的箭头绘制,需要

    反算 atan 角度

    一样的。

    最后这个算是综合的应用,我写了些canvas functions 放到了之前的canvasOverlay 里面去用,可以方便的集成到各种支持canvas 的lib 里面用。

    基本思路就是:(懒得画图了,思路比较简单)

    需要注意的是

    ,atan弧度角的计算在第二三象限,会跟第一四象限混淆。比如向左下角的

    有向线的向量

    是两个负值,但是tan 值是正的,跟第一象限一样,所以反算的时候也会算出来小于90度的角,实际上是大于180 的角度了,需要 +

    大概的绘制过程,code as follow:

    就简单写到这里。

    最近还有个问题提到比较多,关于canvas 上的图标如何贴合地图的倾斜,这也是个视觉上的问题。大抵上可以通过CSS3d 或者 canvas 的透视去做,前者应该更简单些。有空再实践下

  • 绘图软件有哪些?

  • 您好,现如今,市面上的绘图软件是多种多样的,有的侧重于艺术设计,有的侧重于工业图,还有的侧重于3D画图,每一款绘图软件都有它自身的特点。下面看看有哪些主流绘图软件?

    1.Inkscape

    Inkscape是一款国外的矢量图形编辑软件,该软件的开发目标是成为一套强力的绘图软件,且能完全遵循与支持XML、SVG及CSS等开放性的标准格式。

    2.Lucidchart

    Lucidchart是一个基于Html5的在线流程图绘制和协作应用平台,用户可以通过它快速的实现流程图标的绘制,还能实时的进行团队协作。

    3.3D MAX

    3D MAX是一款专业的室内设计效果图制作软件,也是世界上应用最为广泛的三维建模,动画,渲染软件,它被广泛的应用到游戏开发、角色动画、电影电视视觉效果和设计行业等领域。

    4.SmartDraw

    SmartDraw是一款老牌的绘图软件了,它可以轻松创建数据流程图、程序流程图、网络结构图、室内设计图等等。只需利用鼠标拖放相应的图形、线条即可以快速创建出漂亮而又专业的设计图。对于程序设计、网络结构设计等领域的应用来说,SmartDraw绝对算得上是一个短小而又精悍的得力工具了。

    5.CorelDraw

    CorelDraw是一款专业的图形设计软件,它专用于矢量图形的编辑和排版,借助其丰富的内容和专业的图形设计、照片编辑和网站设计软件,能够让你随心所欲地表达自己的风格与创意,轻松创作徽标标志、广告标牌、Web图形或任何原创项目。

    6.CAD

    CAD在设计中通常要用计算机对不同方案进行大量的计算、分析和比较,以决定最优方案。各种设计信息,不管是数字的、文字的或图形的,都可以存放在计算机的内存,并能快速地检索。设计人员通常用草图开始设计,将草图变为工作图的繁重工作可以交给计算机完成。利用计算机可以进行与图形的编辑、放大、缩小、平移和旋转等有关的图形数据加工工作。

    7.Visio

    Visio是微软旗下的一款绘图软件,它可以帮助IT程序员和商务专业人员轻松地可视化、分析和交流复杂信息,让难以理解的复杂文本和表格转换为一目了然的Visio图表,提高工作的效率。

    8.Adobe illustrator

    Adobe illustrator其实与PS有些类似,但它是专业的矢量图形处理软件,为用户提供着丰富的像素描绘功能和顺畅灵活的矢量图编辑功能,并能够快速的创建设计工作流程。

    9.Photoshop

    Photoshop是一款十分强大的图形图像处理软件,其也一直占据着图像处理软件的领袖地位,是平面设计、建筑装修设计、三维动画制作和网页设计的必用软件。

    整理了这么多,希望对您有帮助,望采纳~

  • vuepc电脑可以获取设备吗

  • VUE2实现录像(PC端)可拍照 下载 预览 选取指定摄像头和麦克风设备 源代码可直接使用 原创

    2022-10-16 17:57:44

    嗯呐FT 

    码龄1年

    关注

    2022.10月份 谷歌是最新版本 使用vue2写

    下面的这些代码可以在谷歌浏览器的本地(localhost)和https环境下执行。中间有大量的注释可查看,基本上看一遍就懂,前面的坑我基本都踩过了。

    如果是http环境的话,我下面这些代码是执行不了的,因为我做了获取指定设备的功能,如果要http环境中使用,需要把获取指定设备的相关代码删掉才能用,而且需要去谷歌的这个地址配置一下才能用,最下面我会介绍怎么在http环境中用。

    功能如下:

    1.可获取多个摄像头设备并选择其一进行录制

    2.录制的过程中拔掉摄像头监听结束录制

    3.可在录制中进行拍照生成png图片 可预览 可下载

    4.录制完成会生成一个有声音和画面的webm格式视频 可在线预览下载

    5.录制的过程中计时(最小误差)

    界面展示(界面我就做个小Demo 没有过多去弄好看点 重要是script部分)

    先上代码 -- html部分

    <template>

    <div class="publish">

    <div class="box">

    <div class="videoPart">

    <div class="videoRecord" @mouseenter="hoverVideo(0)" @mouseleave="hoverVideo(1)">

    <video id="videoCamera" :width="videoWidth" :height="videoHeight" autoPlay></video>

    <div class="hoverVideoOutside" v-if="ifHoverVideo && ifStartRecord" >

    <div class="hoverVideoInside">

    <div class="hoverVideoInsideInside">

    <div class="hoverVideoBtn"><div class="hoverVideoBtnInside"></div></div>

    <span>{{recordHMSTime}}</span>

    </div>

    </div>

    </div>

    </div>

    <canvas id="canvasCamera" class="canvas" :width="videoWidth" :height="videoHeight"></canvas>

    <video v-if="showVideo" :src="videoSrc" autoplay controls></video>

    <img v-if="showImg" class="imgClass" :src="imgSrc" alt="">

    </div>

    <div>

    <el-select v-model="deviceId" placeholder="请选择摄像头" @change="selectVideoChange" @focus="findVideoDevice" :disabled="ifStartRecord">

    <el-option

    v-for="item in deviceArr"

    :key=""

    :label=""

    :value="">

    </el-option>

    </el-select>

    <el-button v-if="!ifStartRecord" @click="startRecord" icon="el-icon-video-camera" size="small">开始录制</el-button>

    <el-button v-else @click="stopRecord" icon="el-icon-switch-button" size="small">结束录制</el-button>

    <el-button @click="photographBtn" icon="el-icon-camera" size="small">拍照</el-button>

    </div>

    <vxe-table

    border

    resizable

    show-overflow

    ref="xTable"

    height="500"

    :row-config="{isHover: true}"

    :data="tableData">

    <vxe-column type="seq" width="60"></vxe-column>

    <vxe-column field="name" title="Name"></vxe-column>

    <vxe-column title="操作" width="200" show-overflow>

    <template #default="{ row }">

    <vxe-button type="text" icon="vxe-icon-edit" @click="preview(row)">预览</vxe-button>

    <vxe-button type="text" icon="vxe-icon-edit" @click="download(row)">下载</vxe-button>

    </template>

    </vxe-column>

    </vxe-table>

    </div>

    </div>

    </template>

    CSS代码

    <style scoped>

    .canvas{

    opacity: 0!important;

    }

    .videoPart{

    position: relative;

    display: flex;

    align-items: center;

    }

    .hoverVideoOutside{

    position: absolute;

    top: 0px;

    left: 0px;

    width: 500px;

    height: 300px;

    background:linear-gradient(#000,transparent 20%);

    z-index: 999;

    }

    .hoverVideoInside{

    position: relative;

    width: 100%;

    height: 100%;

    }

    .hoverVideoInsideInside{

    position: absolute;

    top: 10px;

    left: 380px;

    padding: 2px;

    display: flex;

    justify-content: center;

    align-items: center;

    }

    .hoverVideoBtn{

    width: 30px;

    height: 30px;

    border-radius: 50%;

    border: 2px solid red;

    padding: 3px;

    box-sizing: border-box;

    margin-right: 4px;

    }

    .hoverVideoBtnInside{

    background: red;

    width: 20px;

    height: 20px;

    border-radius: 50%;

    box-sizing: 50%;

    }

    span{

    color: #fff;

    }

    .videoRecord{

    position: relative;

    }

    .imgClass{

    width: 500px;

    height: 300px;

    }

    </style>

    逻辑部分

    <script>

    export default {

    name: 'HelloWorld',

    data() {

    return {

    ifOpenCamera: false,//控制摄像头开关

    ifStartRecord:false, //是否开始录制

    thisVideo: null,

    thisContext: null, //canvas

    thisCanvas: null,

    videoWidth: 500,

    videoHeight: 300,

    videoCecorded: [], //接受的数据流

    mediaRecorderData: {},

    videoSrc:'', //录制完的视频预览

    imgSrc:'',//录制完预览的图片地址

    deviceArr:[],//获取该电脑的摄像头

    deviceId:'', //选择哪个摄像头

    tableData:[], //录制完 制作表格数据

    showVideo:false, //录制完预览视频

    showImg:false,//录制完预览图片

    recordTime:0, //监听录像的时间

    recordHMSTime:'00:00:00', //监听录像的时间

    ifHoverVideo:false, //监听是否鼠标在视频的上面 显示录制时间

    timer:null, //每一秒执行一次计算录像的时间 这个是有误差的

    startTime:'', //记录开始录制的时间戳

    stream:null,

    }

    },

    created() {

    ();

    },

    methods: {

    initDevice(){

    this.$nextTick(() => {

    = []

    = null

    = ('canvasCamera');

    = ('2d');

    = ('videoCamera');

    // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象

    ('', )

    if ( === undefined) {

    = {}

    = !;

    ('http环境下没开那个谷歌权限 所以有点问题 得弹出提示弹窗 如果是本地或者https环境就基本不会走到这里')

    this.$message({

    message: '去谷歌浏览器配置网址',

    type: 'error'

    })

    }

    // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象

    // 使用getUserMedia,因为它会覆盖现有的属性。

    // 这里,如果缺少getUserMedia属性,就添加它。

    if ( === undefined) {

    = function (constraints) {

    // 首先获取现存的getUserMedia(如果存在)

    let getUserMedia = || || ;

    // 有些浏览器不支持,会返回错误信息

    // 保持接口一致

    if (!getUserMedia) {

    return (new Error('getUserMedia is not implemented in this browser'))

    }

    // 否则,使用Promise将调用包装到旧的

    return new Promise(function (resolve, reject) {

    (navigator, constraints, resolve, reject)

    })

    }

    }

    ()

    })

    },

    // 每次点开下拉框的时候都要去获取现在有多少个设备 以防在打开这个网站之后把摄像头拔了等情况

    async findVideoDevice(){

    = ''

    = []

    const _this = this

    try{

    // 获取你电脑中有什么设备

    let deviceArr = await ();

    if( == 0){

    this.$message({

    message: '没有摄像头设备',

    type: 'error'

    })

    = []

    return

    }

    ('设备',deviceArr)

    (item=>{

    if( == 'videoinput'){

    (item) //获取你电脑中有多少个摄像头设备

    }

    })

    }catch(error){

    (error)

    = []

    }

    },

    // 选择完是哪个摄像头以后执行的方法

    selectVideoChange(){

    this.$nextTick(() => {

    const _this = this;

    const constraints = {

    audio: true,

    video: {

    width: _,

    height: _,

    transform: 'scaleX(-1)',

    deviceId:{exact:}

    },

    };

    (constraints).then(async(stream)=>{

    // 旧的浏览器可能没有srcObject

    if ('srcObject' in _) {

    _ = stream

    } else {

    // 避免在新的浏览器中使用它,因为它正在被弃用。

    _ = && (stream)

    }

    _ = function (e) {

    _()

    }

    _ = true

    }).catch(err => {

    (err)

    });

    });

    },

    // 开始录制

    startRecord() {

    if( == ''){

    this.$message({

    message: '请选择摄像头',

    type: 'error'

    })

    return

    }

    const _this = this

    = null

    = []

    this.$nextTick(()=>{

    const constraints = {

    audio: true,

    video: {

    width: ,

    height: ,

    transform: 'scaleX(-1)',

    deviceId:{exact:} //选取指定的设备来录制

    },

    };

    //必须在model中render后才可获取到dom节点,直接获取无法获取到model中的dom节点

    (constraints).then(function (stream) {

    _ = stream

    // 这个要重写一次

    // 我插第三方的视频录像设备的情况下 点击录像 然后把设备拔出来 这个时候画面是黑色的

    // 如果没有重写下面的方法 插进设备后 点击录像 画面依然是黑色的 但是能录像 只是界面上不显示

    if ('srcObject' in _) {

    _ = stream

    } else {

    // 避免在新的浏览器中使用它,因为它正在被弃用。

    _ = && (stream)

    }

    _ = function (e) {

    _ = true

    _()

    }

    _(stream);//调用录制控件方法,触发开始录制

    }).catch(err => {

    // 点录制之前断开设备连接 但选择框已经选了设备 就会触发这个err

    (err)

    });

    })

    },

    //拍照按钮

    photographBtn() {

    //先判断是否开启了摄像头

    if(!){

    this.$message({

    message: '摄像头都还没开呢 傻猪猪',

    type: 'error'

    })

    return

    }

    // 点击,canvas画图

    (, 0, 0, , );

    // 如果图片尺寸不想 500 300 那就写下面这个

    // (, 0, 0, , ,0,0,1000, 600);

    const fileName = (new Date).toISOString().replace(/:|\./g,'-')

    const a = ('image/png')

    const file = (a,fileName + 'png')

    ({

    id:2,

    name:fileName + 'png',

    url:('image/png'),

    type:'png'

    })

    },

    //停止录制

    stopRecord() {

    if ( && !== null) {

    (); //结束录制

    }

    },

    // 开始录制中

    startRecording(stream) {

    ('stream 在开始的时候的',stream)

    let _this = this

    = new MediaRecorder(stream, {

    mimeType: 'video/webm;codecs=vp8,opus' //不加这个codecs=vp8,opus有时候下载下来之后看几秒就没了 残缺的视频

    });

    ("dataavailable", (e) => {

    if (e. > 0) {

    _(e.data);//视频录制视频流数据

    };

    });

    ("stop", () => {

    ("结束录制");

    _();//上传实时录制的视频

    _ = false

    _ = 0

    _ = '00:00:00'

    clearTimeout(_)

    _ = null

    });

    ("start", (e) => {

    ("开始 录制");

    _ = true

    _ = 0

    _ = new Date().getTime();

    _ = setTimeout(_,1000)

    });

    ()

    },

    // 上传录制视频方法,获取视频地址

    updataVideo() {

    const blob = new Blob(, {

    type: 'video/webm'

    });

    const fileName = (new Date).toISOString().replace(/:|\./g,'-')

    ({

    id:2,

    type:'webm',

    name:fileName + '.webm',

    url:(blob)

    })

    },

    // 预览视频 图片

    preview(row){

    if( == 'png'){

    = true

    = false

    =

    }else if( == 'webm'){

    = true

    = false

    =

    }else{

    this.$message({

    message: '无法预览',

    type: 'error'

    })

    }

    },

    download(row){

    let aTag = ('a');//创建一个a标签

    = ;

    = ;

    ();

    },

    hoverVideo(num){

    if(num){

    // 移出

    = false

    }else{

    // 移入

    = true

    }

    },

    secondChangeMinute(second){

    const hour = parseInt(second / 3600)

    const min = parseInt(second / 60)

    const se = parseInt(second % 60)

    const cHour = hour<10?'0'+hour:hour

    const cMin = min<10?'0'+min:min

    const cSe = se<10?'0'+se:se

    return cHour + ':' + cMin + ':' + cSe

    },

    fixed(){

    += 1

    = ()

    if(!){

    ()

    }

    var offset = new Date().getTime() - ( + * 1000);

    var nextTime = 1000 - offset;

    if (nextTime < 0) nextTime = 0;

    = setTimeout(, nextTime);

    },

    errReponse(err){

    const message = || err

    const response = {

    'permission denied': '浏览器禁止本页面使用摄像头或麦克风,请开启相关的权限',

    'requested device not found': '未检测到摄像头'

    }

    (response[ () ] || '未知错误');

    this.$message({

    message: response[ () ] || '未知错误',

    type: 'warning'

    })

    },

    dataURLtoFile: function(dataurl, filename) {

    let arr = (','),

    mime = arr[0].match(/:(.*?);/)[1],

    bstr = atob(arr[1]),

    n = ,

    u8arr = new Uint8Array(n);

    while (n--) {

    u8arr[n] = (n);

    }

    return new File([u8arr], filename, { type: mime });

    },

    // 这个方法是给需要的人看的 演示打开摄像头的方法

    async openCamera(){

    await ({audio:true,video:true}).then(()=>{

    //我这个时候已经打开摄像头了

    }).catch(err=>{

    (err)

    })

    },

    // 这个方法是给需要的人看的 演示关闭摄像头的方法

    closeCamera(){

    ().forEach(item => {

    // 关闭当前所有已打开的设备(你刚刚选择的摄像头设备和你默认的麦克风)

    ()

    })

    },

    }

    }

    </script>

    问题解答区域:

    1.录制的视频只能是webm格式吗?进度条呢?

    答:我在写程序的时候发现只能写webm格式,如果是写MP4或者其他类型,视频下载下来是没有办法播放的,可能在移动端就没有问题,我还没有去尝试在移动端做这个功能。webm格式我所知道的有两个弊端,下载下来的时候无法拖动进度条,而且要在指定播放器中才能播放。如果想要解决这个进度条的问题,可以去看这个地址的解决方法。前端 mediaRecorder 录制视频源代码实例,和本地播放器无法定位进度条问题分析和解决_anne都的博客-CSDN博客_mediarecorder 进度条

    2.http问题

    答:在http环境下是可以录制的,但是我上面的代码运行不了就是了。因为我添加了一个获取用户电脑中设备的功能,该功能在http环境下没有办法获取,可能是浏览器出于安全的问题。如果想要在http环境下录制,可以参考下面的这个地址,我也是百度了很久,看了很多别人的博客才得出的最终代码结果。地址如下:

    =>1.JS调用媒体设备失败 --- getUserMedia undefine 问题(各浏览器配置方法)_<!--玄德-->的博客-CSDN博客_浏览器不支持getusermedia

    =>2.

    PC端调用摄像头录制视频――vue标准写法_前端_森森的博客-CSDN博客_vue调用摄像头录像

    =>3.

    JS基于页面实现音视频的录制(一)_画虎成鳖的博客-CSDN博客_js录制视频

    3.表格不一定要用vxetable,随便用

    4.如果还有什么问题再在评论区问吧。。

    最新文章 更多
    最新素材 更多
    公司介绍 网站地图 图片资讯
    Copyright © 2010-2022 山东找图网络科技有限公司  鲁ICP备18007836号-3  邮箱:15653358549@163.com