我的世界新版本为什么不能旋转屏幕VUE如何旋转屏幕

详解vue2.0 不同屏幕适配及px与rem转换问题
转载 &更新时间:日 09:15:02 & 作者:来掘金了
这篇文章主要介绍了详解vue2.0 不同屏幕适配及px与rem转换问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
因为项目需要,vue开发项目,必须将已写的以px为单位的部分,转换为rem。要是全部转换,这大量的计算量,哪怕是sublime Text 的cssrem插件,也是一个庞大的工作量。所以,直接使用插件没商量。
第一步:因为rem是根据更元素来计算大小,所以,捕捉到当前屏幕的大小并赋值给html,这是其一
第二步:使用px2rem插件,来捕捉当前项目的所有px,直接计算相对应数值。
这样,以后写界面,就可以直接用px来构建界面,不用自己去计算啦!
1、安装插件(我是安装了淘宝镜像,所以是cnpm,若是没装淘宝镜像,就npm)
$ cnpm i postcss-px2rem --save
$ cnpm install px2rem-loader --save
2、配置px2rem
build目录下vue-loader.conf.js中,做如下修改:
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
postcss:[require('postcss-px2rem')({'remUnit':37.5,'baseDpr':2})]
/*因为我是以750px(iphone6)宽度为基准,所以remUnit为37.5*/
3、在static目录中,建js文件夹,放flex.js:
(function(win, lib) {
var doc = win.
var docEl = doc.documentE
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
//console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelR
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio &= 3 && (!dpr || dpr &= 3)) {
} else if (devicePixelRatio &= 2 && (!dpr || dpr &= 2)){
// 其他设备下,仍旧使用1倍的方案
scale = 1 /
docEl.setAttribute('data-dpr', dpr);
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
function refreshRem(){
var width = docEl.getBoundingClientRect().
if (width / dpr & 540) {
width = 540 *
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem =
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
refreshRem();
flexible.dpr = win.dpr =
flexible.refreshRem = refreshR
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
})(window, window['lib'] || (window['lib'] = {}));
4、在index.html中,加入flex.js
&script type="text/javascript" src="static/js/flex.js"&&/script&
5、重启项目
大功告成!!
现在你就可以在浏览器中,看到你的px换算成了rem啦!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具共被编辑 2 次
vue.js编写移动端页面,检测旋转屏幕,横竖屏。
初学vue,想要在检测到旋转屏幕后显示遮罩层。现在我的想法是在mounted时期添加监听屏幕旋转事件,如果检测到了,则修改data中的值isShowCover来改变v-show中的真假值,来达到显示隐藏遮罩层的目的。但是mounted时期好像取不到data中的值。我是用alert来判断取不取的到值的.
this.isShowCover 是undefinedthis.showCover() alert都不提示了。this.$options.methods.showCover() alert也不提示了。
所以想问的是想要监听到旋转屏幕事件,这个事件应该加在哪里?检测到旋转屏幕事件后,怎么才能把isShowCover的值改变来显示隐藏遮罩层?data中的值大概是什么时候可以取到并且修改?
提前感谢下回答的大佬。
下面附主要代码。
&template&
&div v-show="isShowCover" style = "position:background:background:rgba(0,0,0,0.5);margin:top:0;bottom:0;left:0;right:0"&
&img src="../../pic/rotatePic.png" style="width:200height:200margin:top:0;bottom:0;left:0;right:0"&
&/template&
export default {
data: () =& ({
isShowCover: false
mounted() {
window.addEventListener(
"onorientationchange" in window ? "orientationchange" : "resize",
function() {
if (window.orientation === 90 || window.orientation === -90) {
//想把下面的alert换成能够控制v-show的代码
this.$options.methods.showCover() +
"横屏可能导致页面异常,建议竖屏操作!"
//alert("123");仅alert纯文本可以正常运行
//window.location.reload();
showCover() {
return "123";
vue.js编写移动端页面,检测旋转屏幕,横竖屏。
初学vue,想要在检测到旋转屏幕后显示遮罩层。现在我的想法是在mounted时期添加监听屏幕旋转事件,如果检测到了,则修改data中的值isShowCover来改变v-show中的真假值,来达到显示隐藏遮罩层的目的。但是mounted时期好像取不到data中的值。我是用alert来判断取不取的到值的.
this.isShowCover 是undefinedthis.showCover() alert都不提示了。this.$options.methods.showCover() alert也不提示了。
所以想问的是想要监听到旋转屏幕事件,这个事件应该加在哪里?检测到旋转屏幕事件后,怎么才能把isShowCover的值改变来显示隐藏遮罩层?data中的值大概是什么时候可以取到并且修改?
提前感谢下回答的大佬。
下面附主要代码。
&template&
&div v-show="isShowCover" style = "position:background:background:rgba(0,0,0,0.5);margin:top:0;bottom:0;left:0;right:0"&
&img src="../../pic/rotatePic.png" style="width:200height:200margin:top:0;bottom:0;left:0;right:0"&
&/template&
export default {
data: () =& ({
isShowCover: false
mounted() {
window.addEventListener(
"onorientationchange" in window ? "orientationchange" : "resize",
function() {
if (window.orientation === 90 || window.orientation === -90) {
this.$options.methods.showCover() +
"横屏可能导致页面异常,建议竖屏操作!"
//alert("123");
//window.location.reload();
showCover() {
return "123";
我要该,理由是:实现效果:
裁切指定区域内的图片
输出bolb 格式数据 提供给 formData 对象
大概原理:
利用h5 FileReader 对象, 获取 &input type="file"/& “上传到浏览器的文件” ,文件形式 为base64形式, 把 base64 赋给canvas的上下文。
然后给canvas 元素上加入对(mousedown)监听事件。 当用户鼠标左键在canvas按下时:
挂载对 window 对象mousemove事件 ---& 获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。
挂载对 window 对象mouseup 事件, 清除 mousemove事件的绑定。(同时该事件触发后会被删除)
剩下的 放大、缩小 、 旋转 是对 canvas 对象的操作/坐标体系的操作。具体api详见mdn canvas 文档
export const on = ({el, type, fn}) =& {
if (typeof window) {
if (window.addEventListener) {
el.addEventListener(type, fn, false)
el.attachEvent(`on${type}`, fn)
export const off = ({el, type, fn}) =& {
if (typeof window) {
if (window.addEventListener) {
el.removeEventListener(type, fn)
el.detachEvent(`on${type}`, fn)
export const once = ({el, type, fn}) =& {
const hyFn = (event) =& {
off({el, type, fn: hyFn})
on({el, type, fn: hyFn})
// 最后一个
export const fbTwice = ({fn, time = 300}) =& {
let [cTime, k] = [null, null]
// 获取当前时间
const getTime = () =& new Date().getTime()
// 混合函数
const hyFn = () =& {
const ags = argments
return () =& {
clearTimeout(k)
k = cTime =
fn(...ags)
return () =& {
if (cTime == null) {
k = setTimeout(hyFn(...arguments), time)
cTime = getTime()
if ( getTime() - cTime & 0) {
// 清除之前的函数堆 ---- 重新记录
clearTimeout(k)
cTime = getTime()
k = setTimeout(hyFn(...arguments), time)
const contains = function(parentNode, childNode) {
if (parentNode.contains) {
return parentNode != childNode && parentNode.contains(childNode)
return !!(parentNode.compareDocumentPosition(childNode) & 16)
export const addClass = function (el, className) {
if (typeof el !== "object") {
console.log('el is not elem')
return null
classList = el['className']
classList = classList === '' ? [] : classList.split(/\s+/)
if (classList.indexOf(className) === -1) {
classList.push(className)
el.className = classList.join(' ')
console.warn('warn className current')
export const removeClass = function (el, className) {
let classList = el['className']
classList = classList === '' ? [] : classList.split(/\s+/)
classList = classList.filter(item =& {
return item !== className
el.className =
classList.join(' ')
export const delay = ({fn, time}) =& {
let oT = null
let k = null
return () =& {
// 当前时间
let cT = new Date().getTime()
const fixFn = () =& {
k = oT = null
if (k === null) {
k = setTimeout(fixFn, time)
if (cT - oT & time) {
clearTimeout(k)
k = setTimeout(fixFn, time)
const Event = function () {
this.typeList = {}
Event.prototype.on = function ({type, fn}){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].push(fn)
this.typeList[type] = []
this.typeList[type].push(fn)
Event.prototype.off = function({type, fn})
if (this.typeList.hasOwnProperty(type)) {
let list = this.typeList[type]
let index = list.indexOf(fn)
if (index !== -1 ) {
list.splice(index, 1)
console.warn('not has this type')
Event.prototype.once = function ({type, fn}) {
const fixFn = () =& {
this.off({type, fn: fixFn})
this.on({type, fn: fixFn})
Event.prototype.trigger = function (type){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].forEach(fn =& {
&template&
&div class="jc-clip-image" :style="{width: `${clip.width}`}"&
&canvas ref="ctx"
:width="clip.width"
:height="clip.height"
@mousedown="handleClip($event)"
&input type="file" ref="file" @change="readFileMsg($event)"&
&div class="clip-scale-btn"&
&a class="add" @click="handleScale(false)"&+&/a&
&a @click="rotate" class="right-rotate"&转&/a&
&a class="poor" @click="handleScale(true)"&-&/a&
&span&{{scale}}&/span&
&div class="upload-warp"&
&a class="upload-btn" @click="dispatchUpload($event)"&upload&/a&
&a class="upload-cancel"&cancel&/a&
&div class="create-canvas"&
&a class="to-send-file" @click="outFile" title="请打开控制台"&生成文件&/a&
&/template&
import {on, off, once} from '../../utils/dom'
export default {
ctx: null,
file: null,
x: 0, // 点击canvas x 鼠标地址
y: 0,// 点击canvas y 鼠标地址
xV: 0, // 鼠标移动 x距离
yV: 0, // 鼠标移动 y距离
nX: 0, // 原始坐标点 图像 x
nY: 0,// 原始坐标点 图像 y
img: null,
type: String,
default: null
type: Object,
default () {
{width: '200px', height: '200px'}
isShow: false,
base64: null,
scale: 1.5, //放大比例
deg: 0 //旋转角度
computed: {
width () {
const {clip} = this
parseFloat(clip.width.replace('px', ''))
height () {
const {clip} = this
parseFloat(clip.height.replace('px', ''))
mounted () {
const {$options, $refs, width, height} = this
// 初始化 canvas file nX nY
Object.assign($options, {
ctx: $refs.ctx.getContext('2d'),
file: $refs.file,
nX: -width / 2,
nY: -height / 2
methods: {
// 旋转操作
rotate () {
const {$options, draw} = this
this.deg = (this.deg + Math.PI /2)% (Math.PI * 2)
draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, this.deg)
// 处理放大
handleScale (flag) {
const {$options, draw, deg} = this
flag && this.scale & 0.1 && (this.scale = this.scale - 0.1)
!flag && this.scale & 1.9 && (this.scale = this.scale + 0.1)
$options.img &&
draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, deg)
// 模拟file 点击事件
dispatchUpload (e) {
this.clearState()
const {file} = this.$options
e.preventDefault()
file.click()
// 读取 input file 信息
readFileMsg () {
const {file} = this.$options
const {draw, createImage, $options: {nX, nY}, scale, deg} = this
const wFile = file.files[0]
const reader = new FileReader()
reader.onload = (e) =& {
const img = createImage(e.target.result, (img) =& {
draw(img, nX, nY, scale, deg)
file.value = null
reader.readAsDataURL(wFile)
// 生成 图像
createImage (src, cb) {
const img = new Image()
this.$el.append(img)
img.className = 'base64-hidden'
img.onload = () =& {
img.src = src
this.$options.img = img
// 操作画布画图
draw (img, x = 0, y = 0, scale = 0.5,deg = Math.PI ) {
const {ctx} = this.$options
let {width, height} = this
// 图片尺寸
let imgW = img.offsetWidth
let imgH = img.offsetHeight
ctx.save()
ctx.clearRect( 0, 0, width, height)
ctx.translate( width / 2, height / 2, img)
ctx.rotate(deg)
ctx.drawImage(img,
y, imgW * scale, imgH * scale)
ctx.restore()
// ... 事件绑定
handleClip (e) {
const {handleMove, $options, deg} = this
if (!$options.img) {
Object.assign(this.$options, {
x: e.screenX,
y: e.screenY
el: window,
type: 'mousemove',
fn: handleMove
el: window,
type: 'mouseup',
fn: (e) =&{
console.log('down')
switch (deg) {
Object.assign($options, {
nX: $options.nX + $options.xV,
nY: $options.nY + $options.yV,
case Math.PI / 2: {
Object.assign($options, {
nX: $options.nY + $options.yV,
nY: $options.nX - $options.xV,
case Math.PI: {
Object.assign($options, {
nX: $options.nX - $options.xV,
nY: $options.nY - $options.yV,
default: {
// $options.nY - $options.yV, $options.nX + $options.xV
Object.assign($options, {
nX: $options.nY - $options.yV,
nY: $options.nX + $options.xV,
el: window,
type: 'mousemove',
fn: handleMove
// ... 处理鼠标移动
handleMove (e){
e.preventDefault()
e.stopPropagation()
const {$options, draw, scale, deg} = this
Object.assign($options, {
xV: e.screenX
- $options.x,
yV: e.screenY - $options.y
switch (deg) {
draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, scale, deg)
case Math.PI / 2: {
draw($options.img, $options.nY + $options.yV, $options.nX - $options.xV, scale, deg)
case Math.PI: {
draw($options.img, $options.nX - $options.xV, $options.nY - $options.yV, scale, deg)
default: {
draw($options.img, $options.nY - $options.yV, $options.nX + $options.xV,
scale, deg)
// 清除状态
clearState () {
const {$options, width, height} = this
if ($options.img) {
this.$el.removeChild($options.img)
Object.assign($options, {
nX: -width / 2,
nY: -height / 2,
img: null,
// 输出文件
outFile () {
const {$refs: {ctx}} = this
console.log(ctx.toDataURL())
ctx.toBlob((blob) =& {console.log(blob)})
@component-namespace jc {
@component clip-image{
width: 100%;
width: 100%;
height: 100%;
box-shadow: 0 0 3px #333;
.base64-hidden {
width: 100%;
z-index: -999;
opacity: 0;
.clip-scale-btn {
margin-bottom: 5
text-align:
height: 20
border-radius: 50%;
background: #49a9
text-align:
&&.poor, &&.right-rotate {
z-index: -9;
width: 100%;
text-align:
height: 20
line-height: 20
.upload-warp {
.upload-btn,.upload-cancel {
display:inline-
height: 25
line-height: 25
border-radius: 5
background: #49a9
box-shadow: 0 0 0 #333;
text-align:
bottom: 0;
margin-top: 5
.upload-cancel{
background:
.to-send-file {
margin-top: 5
height: 25
line-height: 25
border-radius: 5
background: #49a9
项目代码()
0 收藏&&|&&3
谢谢鼓励呀。
谢谢鼓励呀。
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。vue裁切图片实现放大、缩小、旋转功能代码
原创
 10:27:27
689
本文主要和大家介绍了vue实现裁切图片同时实现放大、缩小、旋转功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助到大家。实现效果:裁切指定区域内的图片旋转图片放大图片输出bolb 格式数据 提供给 formData 对象效果图大概原理:利用h5 FileReader 对象, 获取 &input type=&file&/& “上传到浏览器的文件” ,文件形式 为base64形式, 把 base64 赋给canvas的上下文。然后给canvas 元素上加入对(mousedown)监听事件。 当用户鼠标左键在canvas按下时:挂载对 window 对象mousemove事件 ---& 获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。挂载对 window 对象mouseup 事件, 清除 mousemove事件的绑定。(同时该事件触发后会被删除)剩下的 放大、缩小 、 旋转 是对 canvas 对象的操作/坐标体系的操作。具体api详见mdn canvas 文档代码dom.jsexport const on = ({el, type, fn}) =& {
if (typeof window) {
if (window.addEventListener) {
el.addEventListener(type, fn, false)
el.attachEvent(`on${type}`, fn)
export const off = ({el, type, fn}) =& {
if (typeof window) {
if (window.addEventListener) {
el.removeEventListener(type, fn)
el.detachEvent(`on${type}`, fn)
export const once = ({el, type, fn}) =& {
const hyFn = (event) =& {
off({el, type, fn: hyFn})
on({el, type, fn: hyFn})
// 最后一个
export const fbTwice = ({fn, time = 300}) =& {
let [cTime, k] = [null, null]
// 获取当前时间
const getTime = () =& new Date().getTime()
// 混合函数
const hyFn = () =& {
const ags = argments
return () =& {
clearTimeout(k)
k = cTime = null
fn(...ags)
return () =& {
if (cTime == null) {
k = setTimeout(hyFn(...arguments), time)
cTime = getTime()
if ( getTime() - cTime & 0) {
// 清除之前的函数堆 ---- 重新记录
clearTimeout(k)
cTime = getTime()
k = setTimeout(hyFn(...arguments), time)
export const contains = function(parentNode, childNode) {
if (parentNode.contains) {
return parentNode != childNode && parentNode.contains(childNode)
return !!(parentNode.compareDocumentPosition(childNode) & 16)
export const addClass = function (el, className) {
if (typeof el !== &object&) {
console.log('el is not elem')
return null
let classList = el['className']
classList = classList === '' ? [] : classList.split(/\s+/)
if (classList.indexOf(className) === -1) {
classList.push(className)
el.className = classList.join(' ')
console.warn('warn className current')
export const removeClass = function (el, className) {
let classList = el['className']
classList = classList === '' ? [] : classList.split(/\s+/)
classList = classList.filter(item =& {
return item !== className
el.className =
classList.join(' ')
export const delay = ({fn, time}) =& {
let oT = null
let k = null
return () =& {
// 当前时间
let cT = new Date().getTime()
const fixFn = () =& {
k = oT = null
if (k === null) {
k = setTimeout(fixFn, time)
if (cT - oT & time) {
clearTimeout(k)
k = setTimeout(fixFn, time)
export const Event = function () {
this.typeList = {}
Event.prototype.on = function ({type, fn}){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].push(fn)
this.typeList[type] = []
this.typeList[type].push(fn)
Event.prototype.off = function({type, fn}) {
if (this.typeList.hasOwnProperty(type)) {
let list = this.typeList[type]
let index = list.indexOf(fn)
if (index !== -1 ) {
list.splice(index, 1)
console.warn('not has this type')
Event.prototype.once = function ({type, fn}) {
const fixFn = () =& {
this.off({type, fn: fixFn})
this.on({type, fn: fixFn})
Event.prototype.trigger = function (type){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].forEach(fn =& {
}组件模板&template&
&p class=&jc-clip-image& :style=&{width: `${clip.width}`}&&
&canvas ref=&ctx&
:width=&clip.width&
:height=&clip.height&
@mousedown=&handleClip($event)&
&input type=&file& ref=&file& @change=&readFileMsg($event)&&
&p class=&clip-scale-btn&&
&a class=&add& @click=&handleScale(false)&&+&/a&
&a @click=&rotate& class=&right-rotate&&转&/a&
&a class=&poor& @click=&handleScale(true)&&-&/a&
&span&{{scale}}&/span&
&p class=&upload-warp&&
&a class=&upload-btn& @click=&dispatchUpload($event)&&upload&/a&
&a class=&upload-cancel&&cancel&/a&
&p class=&create-canvas&&
&a class=&to-send-file& @click=&outFile& title=&请打开控制台&&生成文件&/a&
&/template&
import {on, off, once} from '../../utils/dom'
export default {
ctx: null,
file: null,
x: 0, // 点击canvas x 鼠标地址
y: 0,// 点击canvas y 鼠标地址
xV: 0, // 鼠标移动 x距离
yV: 0, // 鼠标移动 y距离
nX: 0, // 原始坐标点 图像 x
nY: 0,// 原始坐标点 图像 y
img: null,
type: String,
default: null
type: Object,
default () {
return {width: '200px', height: '200px'}
isShow: false,
base64: null,
scale: 1.5, //放大比例
deg: 0 //旋转角度
computed: {
width () {
const {clip} = this
return parseFloat(clip.width.replace('px', ''))
height () {
const {clip} = this
return parseFloat(clip.height.replace('px', ''))
mounted () {
const {$options, $refs, width, height} = this
// 初始化 canvas file nX nY
Object.assign($options, {
ctx: $refs.ctx.getContext('2d'),
file: $refs.file,
nX: -width / 2,
nY: -height / 2
methods: {
// 旋转操作
rotate () {
const {$options, draw} = this
this.deg = (this.deg + Math.PI /2)% (Math.PI * 2)
draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, this.deg)
// 处理放大
handleScale (flag) {
const {$options, draw, deg} = this
flag && this.scale & 0.1 && (this.scale = this.scale - 0.1)
!flag && this.scale & 1.9 && (this.scale = this.scale + 0.1)
$options.img && draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, deg)
// 模拟file 点击事件
dispatchUpload (e) {
this.clearState()
const {file} = this.$options
e.preventDefault()
file.click()
// 读取 input file 信息
readFileMsg () {
const {file} = this.$options
const {draw, createImage, $options: {nX, nY}, scale, deg} = this
const wFile = file.files[0]
const reader = new FileReader()
reader.onload = (e) =& {
const img = createImage(e.target.result, (img) =& {
draw(img, nX, nY, scale, deg)
file.value = null
reader.readAsDataURL(wFile)
// 生成 图像
createImage (src, cb) {
const img = new Image()
this.$el.append(img)
img.className = 'base64-hidden'
img.onload = () =& {
img.src = src
this.$options.img = img
// 操作画布画图
draw (img, x = 0, y = 0, scale = 0.5,deg = Math.PI ) {
const {ctx} = this.$options
let {width, height} = this
// 图片尺寸
let imgW = img.offsetWidth
let imgH = img.offsetHeight
ctx.save()
ctx.clearRect( 0, 0, width, height)
ctx.translate( width / 2, height / 2, img)
ctx.rotate(deg)
ctx.drawImage(img, x, y, imgW * scale, imgH * scale)
ctx.restore()
// ... 事件绑定
handleClip (e) {
const {handleMove, $options, deg} = this
if (!$options.img) {
Object.assign(this.$options, {
x: e.screenX,
y: e.screenY
el: window,
type: 'mousemove',
fn: handleMove
el: window,
type: 'mouseup',
fn: (e) =&{
console.log('down')
switch (deg) {
Object.assign($options, {
nX: $options.nX + $options.xV,
nY: $options.nY + $options.yV,
case Math.PI / 2: {
Object.assign($options, {
nX: $options.nY + $options.yV,
nY: $options.nX - $options.xV,
case Math.PI: {
Object.assign($options, {
nX: $options.nX - $options.xV,
nY: $options.nY - $options.yV,
default: {
// $options.nY - $options.yV, $options.nX + $options.xV
Object.assign($options, {
nX: $options.nY - $options.yV,
nY: $options.nX + $options.xV,
el: window,
type: 'mousemove',
fn: handleMove
// ... 处理鼠标移动
handleMove (e){
e.preventDefault()
e.stopPropagation()
const {$options, draw, scale, deg} = this
Object.assign($options, {
xV: e.screenX - $options.x,
yV: e.screenY - $options.y
switch (deg) {
draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, scale, deg)
case Math.PI / 2: {
draw($options.img, $options.nY + $options.yV, $options.nX - $options.xV, scale, deg)
case Math.PI: {
draw($options.img, $options.nX - $options.xV, $options.nY - $options.yV, scale, deg)
default: {
draw($options.img, $options.nY - $options.yV, $options.nX + $options.xV, scale, deg)
// 清除状态
clearState () {
const {$options, width, height} = this
if ($options.img) {
this.$el.removeChild($options.img)
Object.assign($options, {
nX: -width / 2,
nY: -height / 2,
img: null,
// 输出文件
outFile () {
const {$refs: {ctx}} = this
console.log(ctx.toDataURL())
ctx.toBlob((blob) =& {console.log(blob)})
@component-namespace jc {
@component clip-image{
width: 100%;
width: 100%;
height: 100%;
box-shadow: 0 0 3px #333;
.base64-hidden {
width: 100%;
z-index: -999;
opacity: 0;
.clip-scale-btn {
margin-bottom: 5
text-align:
height: 20
border-radius: 50%;
background: #49a9
text-align:
&&.poor, &&.right-rotate {
z-index: -9;
width: 100%;
text-align:
height: 20
line-height: 20
.upload-warp {
.upload-btn,.upload-cancel {
display:inline-
height: 25
line-height: 25
border-radius: 5
background: #49a9
box-shadow: 0 0 0 #333;
text-align:
bottom: 0;
margin-top: 5
.upload-cancel{
background:
.to-send-file {
margin-top: 5
height: 25
line-height: 25
border-radius: 5
background: #49a9
}以上就是vue裁切图片实现放大、缩小、旋转功能代码的详细内容,更多请关注php中文网其它相关文章!
江湖传言:PHP是世界上最好的编程语言。真的是这样吗?这个梗究竟是从哪来的?学会本课程,你就会明白了。
PHP中文网出品的PHP入门系统教学视频,完全从初学者的角度出发,绝不玩虚的,一切以实用、有用...
ThinkPHP是国内最流行的中文PHP开发框架,也是您Web项目的最佳选择。《php.cn独孤九贱(5)-ThinkPHP5视频教程》课程以ThinkPHP5最新版本为例,从最基本的框架常识开始,将...
《php.cn原创html5视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了HTML知识。
本套教程,以一个真实的学校教学管理系统为案例,手把手教会您如何在一张白纸上,从零开始,一步一步的用ThinkPHP5框架快速开发出一个商业项目。
所有计算机语言的学习都要从基础开始,《PHP入门视频教程之一周学会PHP》不仅是PHP的基础部分更主要的是PHP语言的核心技术,是学习PHP必须掌握的内容,任何PHP项目的实现都离不开这部分的内容,通...
本课以最新版ThinkPHP5.0.10为基础进行开发,全程实录一个完整企业点,从后台到前台,从控制器到路由的全套完整教程,不论是你是新人,还是有一定开发经验的程序员,都可以从中学到实用的知识~~
ThinkPHP是一个快速、开源的轻量级国产PHP开发框架,是业内最流行的PHP框架之一。本课程以博客系统为例,讲述如何使用TP实战开发,从中学习Thinkphp的实践应用。模版下载地址:http:/...
本课程是php实战开发课程,以爱奇艺电影网站为蓝本从零开发一个自己的网站。目的是让大家了解真实项目的架构及开发过程
本课以一个极简的PHP开发框架为案例,向您展示了一个PHP框架应该具有的基本功能,以及具体的实现方法,让您快速对PHP开发框架的底层实现有一个清楚的认识,为以后学习其实的开发框架打下坚实的基础。
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。...
本站9月直播课已经结束,本套教程是直播实录,没有报上名或者漏听学员福利来了,赶紧看看吧,说不定这里就有你的菜
轻松明快,简洁生动,让你快速走入HTML5的世界,体会语义化开发的魅力
JavaScript能够称得上是史上使用最广泛的编程语言,也是前端开发必须掌握的三技能之一:描述网页内容的HTML、描述网页样式的CSS以及描述网页行为的JavaScript。本章节将帮助大家迅速掌握...
Bootstrap 是最受欢迎的 HTML、CSS 和 JS 框架,用于开发响应式布局、移动设备优先的 WEB 项目。为所有开发者、所有应用场景而设计,它让前端开发更快速、简单,所有开发者都能快速上手...
《php.cn独孤九贱(2)-css视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了CSS知识...
《php用户注册登录系统》主要介绍网站的登录注册功能,我们会从最简单的实现登录注册功能开始,增加验证码,cookie验证等,丰富网站的登录注册功能
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的...
《PHP学生管理系统视频教程》主要给大家讲解了HTML,PHP,MySQL之间的相互协作,实现动态的网页显示和获取数据.
《弹指间学会HTML视频教程》从最基本的概念开始讲起,步步深入,带领大家学习HTML,了解各种常用标签的意义以及基本用法,学习HTML知识为以后的学习打下基础
《最新微信小程序开发视频教程》本节课程是由微趋道录制,讲述了如何申请一个微信小程序,以及开发中需要使用哪些工具,和需要注意哪些等。
全栈工程师
文章总浏览数

我要回帖

更多关于 我的世界新版本为什么不能旋转屏幕 的文章

 

随机推荐