我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么使用Vue实现移动端图片裁剪组件功能

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么使用Vue实现移动端图片裁剪组件功能

本篇内容主要讲解“怎么使用Vue实现移动端图片裁剪组件功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Vue实现移动端图片裁剪组件功能”吧!

  一、组件的初始化参数

  1、图片img(url或者base64 data-url)

  2、截图的宽clipperImgWidth

  3、截图的高clipperImgHeight

props: {  img: String, //url或dataUrl  clipperImgWidth: {    type: Number,    default: 500  },  clipperImgHeight: {    type: Number,    default: 200  }}

  二、布局

  在Z轴方向看主要是由4层组成。第1层是一个占满整个容器的canvas(称cCanvas);第2层是一个有透明度的遮罩层;第3层是裁剪的区域(示例图中的白色方框),里面包含一个与裁剪区域大小相等的canvas(称pCanvas);第4层是一个透明层gesture-mask,用作绑定touchstart,touchmove,touchend事件。其中两个canvas都会加载同一张图片,只是起始坐标不一样。为什么需要两个canvas?因为想做出当手指离开屏幕时,裁剪区域外的部分表面会有一个遮罩层的效果,这样能突出裁剪区域的内容。

<div class="cut-container" ref="cut">  <canvas ref="canvas"></canvas>  <!-- 裁剪部分 -->  <div class="cut-part">    <div class="pCanvas-container">      <canvas ref="pCanvas"></canvas>    </div>  </div>  <!-- 底部操作栏 -->  <div class="action-bar">    <button class="btn-cancel" @click="_cancel">取消</button>    <button class="btn-ok" @click="_cut">确认</button>  </div>  <!-- 背景遮罩 -->  <div class="mask" :class="{opacity: maskShow}"></div>  <!-- 手势操作层 -->  <div class="gesture-mask" ref="gesture"></div></div>

  三、初始化canvas

  canvas绘制的图片在hdpi显示屏上会出现模糊,具体原因这里不作分析,可以参考下这里。我这里的做法是让canvas的width与height为其css width/height的devicePixelRatio倍,以及调用canvas api时所传入的参数都要乘以window.devicePixelRatio。最后还要记录一下两个canvas坐标原点的x, y差值(originXDiff与originYDiff)。如下

_ratio(size) {  return parseInt(window.devicePixelRatio * size);},_initCanvas() {  let $canvas = this.$refs.canvas,    $pCanvas = this.$refs.pCanvas,    clipperClientRect = this.$refs.clipper.getBoundingClientRect(),    clipperWidth = parseInt(this.clipperImgWidth / window.devicePixelRatio),    clipperHeight = parseInt(this.clipperImgHeight / window.devicePixelRatio);  this.ctx = $canvas.getContext('2d');  this.pCtx = $pCanvas.getContext('2d');  //判断clipperWidth与clipperHeight有没有超过容器值  if (clipperWidth < 0 || clipperWidth > clipperClientRect.width) {    clipperWidth = 250  }  if (clipperHeight < 0 || clipperHeight > clipperClientRect.height) {    clipperHeight = 100  }  //因为canvas在手机上会被放大,因此里面的内容会模糊,这里根据手机的devicePixelRatio来放大canvas,然后再通过设置css来收缩,因此关于canvas的所有值或坐标都要乘以devicePixelRatio  $canvas.style.width = clipperClientRect.width + 'px';  $canvas.style.height = clipperClientRect.height + 'px';  $canvas.width = this._ratio(clipperClientRect.width);  $canvas.height = this._ratio(clipperClientRect.height);  $pCanvas.style.width = clipperWidth + 'px';  $pCanvas.style.height = clipperHeight + 'px';  $pCanvas.width = this._ratio(clipperWidth);  $pCanvas.height = this._ratio(clipperHeight);  //计算两个canvas原点的x y差值  let cClientRect = $canvas.getBoundingClientRect(),    pClientRect = $pCanvas.getBoundingClientRect();  this.originXDiff = pClientRect.left - cClientRect.left;  this.originYDiff = pClientRect.top - cClientRect.top;  this.cWidth = cClientRect.width;  this.cHeight = cClientRect.height;}

  四、加载图片

  加载图片比较简单,首先是创建一个Image对象并监听器onload事件(因为加载的图片有可能是跨域的,因此要设置其crossOrigin属性为Anonymous,然后服务器上要设置Access-Control-Allow-Origin响应头)。加载的图片如果宽高大于容器的宽高,要对其进行缩小处理。最后垂直水平居中显示()(这里注意的是要保存图片绘制前的宽高值,因为日后缩放图片是以该值为基础再乘以缩放倍率,这里取imgStartWidth,imgStartHeight)如下

_loadImg() {  if (this.imgLoading || this.loadImgQueue.length === 0) {    return;  }  let img = this.loadImgQueue.shift();  if (!img) {    return;  }  let $img = new Image(),    onLoad = e => {      $img.removeEventListener('load', onLoad, false);      this.$img = $img;      this.imgLoaded = true;      this.imgLoading = false;      this._initImg($img.width, $img.height);      this.$emit('loadSuccess', e);      this.$emit('loadComplete', e);      this._loadImg();    },    onError = e => {      $img.removeEventListener('error', onError, false);      this.$img = $img = null;      this.imgLoading = false;      this.$emit('loadError', e);      this.$emit('loadComplete', e);      this._loadImg();    };  this.$emit('beforeLoad');  this.imgLoading = true;  this.imgLoaded = false;  $img.class="lazy" data-src = this.img;  $img.crossOrigin = 'Anonymous'; //因为canvas toDataUrl不能操作未经允许的跨域图片,这需要服务器设置Access-Control-Allow-Origin头  $img.addEventListener('load', onLoad, false);  $img.addEventListener('error', onError, false);}_initImg(w, h) {  let eW = null,    eH = null,    maxW = this.cWidth,    maxH = this.cHeight - this.actionBarHeight;  //如果图片的宽高都少于容器的宽高,则不做处理  if (w <= maxW && h <= maxH) {    eW = w;    eH = h;  } else if (w > maxW && h <= maxH) {    eW = maxW;    eH = parseInt(h / w * maxW);  } else if (w <= maxW && h > maxH) {    eW = parseInt(w / h * maxH);    eH = maxH;  } else {    //判断是横图还是竖图    if (h > w) {      eW = parseInt(w / h * maxH);      eH = maxH;    } else {      eW = maxW;      eH = parseInt(h / w * maxW);    }  }  if (eW <= maxW && eH <= maxH) {    //记录其初始化的宽高,日后的缩放功能以此值为基础    this.imgStartWidth = eW;    this.imgStartHeight = eH;    this._drawImage((maxW - eW) / 2, (maxH - eH) / 2, eW, eH);  } else {    this._initImg(eW, eH);  }}

   五、绘制图片

  下面的_drawImage有四个参数,分别是图片对应cCanvas的x,y坐标以及图片目前的宽高w,h。函数首先会清空两个canvas的内容,方法是重新设置canvas的宽高。然后更新组件实例中对应的值,最后再调用两个canvas的drawImage去绘制图片。对于pCanvas来说,其绘制的图片坐标值为x,y减去对应的originXDiff与originYDiff(其实相当于切换坐标系显示而已,因此只需要减去两个坐标系原点的x,y差值即可)。看看代码

_drawImage(x, y, w, h) {  this._clearCanvas();  this.imgX = parseInt(x);  this.imgY = parseInt(y);  this.imgCurrentWidth = parseInt(w);  this.imgCurrentHeight = parseInt(h);  //更新canvas  this.ctx.drawImage(this.$img, this._ratio(x), this._ratio(y), this._ratio(w), this._ratio(h));  //更新pCanvas,只需要减去两个canvas坐标原点对应的差值即可  this.pCtx.drawImage(this.$img, this._ratio(x - this.originXDiff), this._ratio(y - this.originYDiff), this._ratio(w), this._ratio(h));},_clearCanvas() {  let $canvas = this.$refs.canvas,    $pCanvas = this.$refs.pCanvas;  $canvas.width = $canvas.width;  $canvas.height = $canvas.height;  $pCanvas.width = $pCanvas.width;  $pCanvas.height = $pCanvas.height;}

   六、移动图片

  移动图片实现非常简单,首先给gesture-mask绑定touchstart,touchmove,touchend事件,下面分别介绍这三个事件的内容

  首先定义四个变量scx, scy(手指的起始坐标),iX,iY(图片目前的坐标,相对于cCanvas)。

  1、touchstart

    方法很简单,就是获取touches[0]的pageX,pageY来更新scx与scy以及更新iX与iY

  2、touchmove

    获取touches[0]的pageX,声明变量f1x存放,移动后的x坐标等于iX + f1x - scx,y坐标同理,最后调用_drawImage来更新图片。

  看看代码吧

_initEvent() {  let $gesture = this.$refs.gesture,    scx = 0,    scy = 0;  let iX = this.imgX,    iY = this.imgY;  $gesture.addEventListener('touchstart', e => {    if (!this.imgLoaded) {      return;    }    let finger = e.touches[0];      scx = finger.pageX;      scy = finger.pageY;      iX = this.imgX;      iY = this.imgY;    }, false);  $gesture.addEventListener('touchmove', e => {    e.preventDefault();    if (!this.imgLoaded) {      return;    }    let f1x = e.touches[0].pageX,      f1y = e.touches[0].pageY;      this._drawImage(iX + f1x - scx, iY + f1y - scy, this.imgCurrentWidth, this.imgCurrentHeight);  }, false);}

   七、缩放图片(这里不作特别说明的坐标都是相对于cCanvas坐标系)

  绘制缩放后的图片无非需要4个参数,缩放后图片左上角的坐标以及宽高。求宽高相对好办,宽高等于imgStartWidth * 缩放比率与imgstartHeight * 缩放倍率(imgStartWidth ,imgstartHeight 上文第四节有提到)。接下来就是求缩放倍率的问题了,首先在touchstart事件上求取两手指间的距离d1;然后在touchmove事件上继续求取两手指间的距离d2,当前缩放倍率= 初始缩放倍率 + (d2-d1) / 步长(例如每60px算0.1),touchend事件上让初始缩放倍率=当前缩放倍率。

  至于如何求取缩放后图片左上角的坐标值,在草稿纸上画来画去,画了很久......终于有点眉目。首先要找到一个缩放中心(这里做法是取双指的中点坐标,但是这个坐标必须要位于图片上,如果不在图片上,则取图片上离该中点坐标最近的点),然后存在下面这个等式

  (缩放中心x坐标 - 缩放后图片左上角x坐标)/ 缩放后图片的宽度 = (缩放中心x坐标 - 缩放前图片左上角x坐标)/ 缩放前图片的宽度;(y坐标同理)

  接下来看看下面这个例子(在visio找了很久都没有画坐标系的功能,所以只能手工画了)

  怎么使用Vue实现移动端图片裁剪组件功能

  绿色框是一张10*5的图片,蓝色框是宽高放大两倍后的图片20*10,根据上面的公式推算的x2 = sx - w2(sx - x1) / w1,y2 = sy - h3(sy - y1) / h2。

  坚持...继续看看代码吧

_initEvent() {  let $gesture = this.$refs.gesture,    cClientRect = this.$refs.canvas.getBoundingClientRect(),    scx = 0, //对于单手操作是移动的起点坐标,对于缩放是图片距离两手指的中点最近的图标。    scy = 0,    fingers = {}; //记录当前有多少只手指在触控屏幕  //one finger  let iX = this.imgX,    iY = this.imgY;  //two finger  let figureDistance = 0,    pinchScale = this.imgScale;  $gesture.addEventListener('touchstart', e => {    if (!this.imgLoaded) {      return;    }    if (e.touches.length === 1) {      let finger = e.touches[0];      scx = finger.pageX;      scy = finger.pageY;      iX = this.imgX;      iY = this.imgY;      fingers[finger.identifier] = finger;    } else if (e.touches.length === 2) {      let finger1 = e.touches[0],        finger2 = e.touches[1],        f1x = finger1.pageX - cClientRect.left,        f1y = finger1.pageY - cClientRect.top,        f2x = finger2.pageX - cClientRect.left,        f2y = finger2.pageY - cClientRect.top;      scx = parseInt((f1x + f2x) / 2);      scy = parseInt((f1y + f2y) / 2);      figureDistance = this._pointDistance(f1x, f1y, f2x, f2y);      fingers[finger1.identifier] = finger1;      fingers[finger2.identifier] = finger2;      //判断变换中点是否在图片中,如果不是则去离图片最近的点      if (scx < this.imgX) {        scx = this.imgX;      }      if (scx > this.imgX + this.imgCurrentWidth) {        scx = this.imgX + this.imgCurrentHeight;      }      if (scy < this.imgY) {        scy = this.imgY;      }      if (scy > this.imgY + this.imgCurrentHeight) {        scy = this.imgY + this.imgCurrentHeight;      }    }  }, false);  $gesture.addEventListener('touchmove', e => {    e.preventDefault();    if (!this.imgLoaded) {      return;    }    this.maskShowTimer && clearTimeout(this.maskShowTimer);    this.maskShow = false;    if (e.touches.length === 1) {      let f1x = e.touches[0].pageX,        f1y = e.touches[0].pageY;      this._drawImage(iX + f1x - scx, iY + f1y - scy, this.imgCurrentWidth, this.imgCurrentHeight);    } else if (e.touches.length === 2) {      let finger1 = e.touches[0],        finger2 = e.touches[1],        f1x = finger1.pageX - cClientRect.left,        f1y = finger1.pageY - cClientRect.top,        f2x = finger2.pageX - cClientRect.left,        f2y = finger2.pageY - cClientRect.top,        newFigureDistance = this._pointDistance(f1x, f1y, f2x, f2y),        scale = this.imgScale + parseFloat(((newFigureDistance - figureDistance) / this.imgScaleStep).toFixed(1));      fingers[finger1.identifier] = finger1;      fingers[finger2.identifier] = finger2;      if (scale !== pinchScale) {        //目前缩放的最小比例是1,最大是5        if (scale < this.imgMinScale) {          scale = this.imgMinScale;        } else if (scale > this.imgMaxScale) {          scale = this.imgMaxScale;        }        pinchScale = scale;        this._scale(scx, scy, scale);      }    }  }, false);  $gesture.addEventListener('touchend', e => {    if (!this.imgLoaded) {      return;    }    this.imgScale = pinchScale;    //从finger删除已经离开的手指    let touches = Array.prototype.slice.call(e.changedTouches, 0);    touches.forEach(item => {      delete fingers[item.identifier];    });    //迭代fingers,如果存在finger则更新scx,scy,iX,iY,因为可能缩放后立即单指拖动    let i,      fingerArr = [];    for(i in fingers) {      if (fingers.hasOwnProperty(i)) {        fingerArr.push(fingers[i]);      }    }    if (fingerArr.length > 0) {      scx = fingerArr[0].pageX;      scy = fingerArr[0].pageY;      iX = this.imgX;      iY = this.imgY;    } else {      this.maskShowTimer = setTimeout(() => {        this.maskShow = true;      }, 300);    }    //做边界值检测    let x = this.imgX,      y = this.imgY,      pClientRect = this.$refs.pCanvas.getBoundingClientRect();    if (x > pClientRect.left + pClientRect.width) {      x = pClientRect.left    } else if (x + this.imgCurrentWidth < pClientRect.left) {      x = pClientRect.left + pClientRect.width - this.imgCurrentWidth;    }    if (y > pClientRect.top + pClientRect.height) {      y = pClientRect.top;    } else if (y + this.imgCurrentHeight < pClientRect.top) {      y = pClientRect.top + pClientRect.height - this.imgCurrentHeight;    }    if (this.imgX !== x || this.imgY !== y) {      this._drawImage(x, y, this.imgCurrentWidth, this.imgCurrentHeight);    }  });},_scale(x, y, scale) {  let newPicWidth = parseInt(this.imgStartWidth * scale),    newPicHeight = parseInt(this.imgStartHeight * scale),    newIX = parseInt(x - newPicWidth * (x - this.imgX) / this.imgCurrentWidth),    newIY = parseInt(y - newPicHeight * (y - this.imgY) / this.imgCurrentHeight);  this._drawImage(newIX, newIY, newPicWidth, newPicHeight);},_pointDistance(x1, y1, x2, y2) {  return parseInt(Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));}

说明一下fingers是干嘛的,是用来记录当前有多少只手指在屏幕上触摸。可能会出现这种情况,双指缩放后,其中一只手指移出显示屏,而另外一个手指在显示屏上移动。针对这种情况,要在touchend事件上根据e.changedTouches来移除fingers里已经离开显示屏的finger,如果此时fingers里只剩下一个finger,则更新scx,scy,iX,iY为移动图片做初始化准备。

八、裁剪图片

这里很简单,就调用pCanvas的toDataURL方法就可以了

_clipper() {  let imgData = null;  try {    imgData = this.$refs.pCanvas.toDataURL();  } catch (e) {    console.error('请在response header加上Access-Control-Allow-Origin,否则canvas无法裁剪未经许可的跨域图片');  }  this.$emit('sure', imgData);}

到此,相信大家对“怎么使用Vue实现移动端图片裁剪组件功能”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么使用Vue实现移动端图片裁剪组件功能

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么使用Vue实现移动端图片裁剪组件功能

本篇内容主要讲解“怎么使用Vue实现移动端图片裁剪组件功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Vue实现移动端图片裁剪组件功能”吧!  一、组件的初始化参数  1、图片img(
2023-07-04

如何用Vue实现图片裁剪组件

这篇文章主要介绍“如何用Vue实现图片裁剪组件”,在日常操作中,相信很多人在如何用Vue实现图片裁剪组件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何用Vue实现图片裁剪组件”的疑惑有所帮助!接下来,请跟
2023-06-20

前端vue cropperjs怎么实现图片裁剪

这篇文章主要介绍“前端vue cropperjs怎么实现图片裁剪”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“前端vue cropperjs怎么实现图片裁剪”文章能帮助大家解决问题。图片裁剪图片裁剪
2023-07-02

cropperjs怎么实现裁剪图片功能

这篇“cropperjs怎么实现裁剪图片功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“cropperjs怎么实现裁剪图片
2023-06-29

Java是怎么实现图片裁剪功能的

今天就跟大家聊聊有关Java是怎么实现图片裁剪功能的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。前言下面提供将图片按照自定义尺寸进行裁剪的Java工具类,一如既往的实用主义。Mav
2023-06-29

使用css怎么实现动态图片裁剪

今天就跟大家聊聊有关使用css怎么实现动态图片裁剪,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
2023-06-09

Vue怎么实现裁切图片功能

今天小编给大家分享一下Vue怎么实现裁切图片功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。效果:1)、安装 vue-cr
2023-06-30

Java中怎么实现一个图片剪裁功能

Java中怎么实现一个图片剪裁功能,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Listing1: 引入的类import java.awt.Graphics; impor
2023-06-17

使用Java代码在Android中实现图片裁剪功能

前言 Android应用中经常会遇到上传相册图片的需求,这里记录一下如何进行相册图片的选取和裁剪。 相册选取图片 1. 激活相册或是文件管理器,来获取相片,代码如下:private static final int TAKE_PICTURE
2022-06-06

thinkphp框架中的图片旋转裁剪功能怎么实现

这篇文章主要讲解了“thinkphp框架中的图片旋转裁剪功能怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“thinkphp框架中的图片旋转裁剪功能怎么实现”吧!第一步:安装think
2023-07-06

JS怎么利用clip-path实现动态区域裁剪功能

这篇文章给大家介绍JS怎么利用clip-path实现动态区域裁剪功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。背景今天逛 CodePen,看到了这样一个非常有意思的效果:CodePen Demo -- Materi
2023-06-22

怎么利用vue组件实现图片的拖拽和缩放功能

这篇文章将为大家详细讲解有关怎么利用vue组件实现图片的拖拽和缩放功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言vue实现一个组件其实很简单但是要写出一个好的可复用的组件那就需要多学
2023-06-26

如何使用Vue全家桶实现移动端音乐功能

今天小编给大家分享一下如何使用Vue全家桶实现移动端音乐功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。src/ 文件目录
2023-07-04

uniapp使用u-upload组件来实现图片上传功能

最近在用uniapp开发微信小程序,下面这篇文章主要给大家介绍了关于uniapp使用u-upload组件来实现图片上传功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-01-03

怎么使用Vue实现鼠标悬浮更换图片功能

今天小编给大家分享一下怎么使用Vue实现鼠标悬浮更换图片功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。首先将所有的选中后
2023-07-04

怎么在Vue中使用better-scroll组件实现横向滚动功能

怎么在Vue中使用better-scroll组件实现横向滚动功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、滚动的实现原理better-scroll的滚动
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录