GithubHelp home page GithubHelp logo

pengjiyuan / omg Goto Github PK

View Code? Open in Web Editor NEW
127.0 3.0 16.0 13.28 MB

:art: 一个让你跳过canvas,直接绘图的 2d 绘图库,上手简单,接口简洁,功能丰富.

Home Page: https://omg.js.org/

License: MIT License

JavaScript 100.00%
drag-drop canvas light-canvas-library drawing shapes

omg's Introduction

omg.js

一个让你跳过canvas,直接绘图的 2d 绘图库,上手简单,接口简洁,功能丰富.

在线示例

English Document

如何安装omg?

NPM

npm i omg.js

CDN

https://unpkg.com/[email protected]/dist/omg.min.js (你可以修改 @version 来改变引用的版本)

下载

源代码

使用方法

  • ES6
import omg from 'omg.js';

const stage = omg({
  ...
});

// Init
stage.init();
  • 浏览器
<script src="yourpath/omg.min.js"></script>
<script>
  var stage = omg({
    ...
  });
  stage.init();
</script>

示例

import omg from 'omg.js';

const stage = omg({
  element: document.getElementById('canvas'),
  width: 500,
  height: 500,
  enableGlobalTranslate: true,
  enableGlobalScale: true,
  position: 'absolute', // 改变canvas.style.position
  images: [], // 预加载的图片列表,通常不用指定,因为使用接口绘制图片的时候,会自动预加载。
  prepareImage: true, // 是否开启预加载图片
  // 活着
  prepareImage: () => {
    // 如果prepareImage指定一个函数的话,也表示开启预加载图片,而且在加载完成后,会触发这个回调函数。
    hideLoading();
  }
});

// 在init之前,你可以通过`stage.extend(yourShape)`拓展自定义的图形。
stage.init();

const rect = stage.graphs.rectangle({
  x: 120,
  y: 120,
  width: 200,
  height: 200,
  color: '#'+(~~(Math.random()*(1<<24))).toString(16)
}).on('mousedown', function() {
  console.log('click rect2');
}).on('mouseenter', function() {
  rect.color = '#'+(~~(Math.random()*(1<<24))).toString(16);
  stage.redraw();
}).on('mouseleave', function() {
  rect.color = '#'+(~~(Math.random()*(1<<24))).toString(16);
  stage.redraw();
}).on('dragin', function() {
  console.log('drag in rect2');
  rect.color = '#ffffff';
  stage.redraw();
}).on('dragout', function() {
  console.log('drag out rect2');
  rect.color = '#'+(~~(Math.random()*(1<<24))).toString(16);
  stage.redraw();
}).on('drop', function() {
  console.log('you drop on the rect2!');
  rect.color = '#000';
  stage.redraw();
}).config({
  drag: true,
  changeIndex: true
});

// 把图形添加到待绘制的列表中.
stage.addChild(rect);

// 绘制,并且绑定事件。
stage.show();

图形列表

矩形

const rect = stage.graphs.rectangle({
  x: 0,
  y: 0,
  width: 110,
  height: 110,
  rotate: 45, // 如果指定了radius的话,rotate会出现异常(待修复)
  radius: {
    tl: 6, // 左上
    tr: 6, // 右上
    bl: 6, // 左下
    br: 6  // 右下
  },
  color: '#514022'
});

折线

const polyline = stage.graphs.line({
  matrix: [
    [10, 180],
    [40, 50],
    [80, 180],
    [90, 80],
    [110, 100],
    [140, 50],
    [260, 180]
  ]
});

不规则多边形

const polygon = stage.graphs.polygon({
  matrix: [
    [310, 120],
    [360, 120],
    [348, 230],
    [250, 340],
    [146, 200]
  ],
  color: 'black',
  style: 'stroke',
  lineWidth: 4
});

图片

const image = stage.graphs.image({
  x: 0,
  y: 0,
  width: 800,
  height: 500,
  src: './img/timg.jpg'
});

// 支持canvas绘制图片的所有接口.
const image3 = stage.graphs.image({
  x: 200,
  y: 200,
  width: 97,
  height: 110,
  sliceX: 5,
  sliceY: 0,
  sliceWidth: 97,
  sliceHeight: 110,
  src: './img/action.png'
});

文字

const text = stage.graphs.text({
  x: 300,
  y: 40,
  width: 150,
  height: 40, // x, y, width, height指定了一个矩形, 文字就在其中
  paddingTop: 8, // 用于调整文字在矩形中的位置
  center: true,  // 文字居中
  background: {
    color: 'blue', // 背景颜色
    img: './img/text_bg.png' // 背景图片
  }, // 给文字添加背景颜色(矩形)
  font: 'italic bold 20px arial,sans-serif', // 文字样式
  text: 'Hello stage', // 文字内容
  color: '#fff', // 文字颜色
  style: 'fill' // fill -- 填充, stroke -- 描边
});

圆形

const arc = stage.graphs.arc({
  x: 400,
  y: 400,
  radius: 30,
  color: 'rgba(255, 255, 255, 0.5)',
  style: 'fill' // fill -- 填充, stroke -- 描边
});

扇形

const arcb = stage.graphs.arc({
  x: 130,
  y: 380,
  radius: 100,
  startAngle: 45,
  endAngle: 165,
  color: '#512854',
  style: 'fill'
});

隐藏图形

const arcb = stage.graphs.arc({
  ...,
  hide: true
});

// 或者

arcb.hide = true;

拓展图形

如果omg提供的默认图形不够用, 你可以轻松拓展自定义图形. 在init之前, 你可以通过 extend 方法来拓展自定义图形.

const stage = omg({
  ...
});

const yourShape = function(settings, _this) {
  const draw = function() {
    const canvas = _this.canvas;
    const scale = _this.scale;

    // 如果你想要自定义图形支持drag, scale, mousedown, mouseenter等事件,你必须添加这一行
    stage.ext.DefineScale.call(this, scale, 'moveX', 'moveY', 'matrix');

    const matrix = this.scaled_matrix;

    canvas.save();
    canvas.translate(this.scaled_moveX, this.scaled_moveY);
    canvas.beginPath();

    matrix.forEach((point, i) => {
      i === 0 ? canvas.moveTo(point[0], point[1]) : canvas.lineTo(point[0], point[1]);
    });
    canvas.lineTo(matrix[0][0], matrix[0][1]);
    
    canvas.fillStyle = this.color;
    canvas.fill();
    canvas.closePath();
    canvas.restore();
  };

  return Object.assign({}, stage.ext.display(settings, _this), {
    type: 'polygon',
    draw: draw,
    lineWidth: settings.lineWidth || 1,
    matrix: settings.matrix
  });
};

// 在init之前,拓展自定义图形.
stage.extend({
  yourShape: yourShape
});

stage.init();

// 使用自定义图形
const shape = stage.graphs.yourShape({
  ...settings
});

stage.addChild(shape);

stage.show();

添加事件

全局事件

给全局canvas添加的 (mousedown, mousemove) 事件.

stage.mousedown(function(e) {
  console.log(stage.utils.getPos(e));
});

stage.mousemove(function(e) {
  console.log(stage.utils.getPos(e));
});

给图形添加事件

所有pc端支持的事件:

  • mousedown
  • mouseup
  • mouseenter
  • mouseleave
  • mousemove'
  • drag
  • dragend
  • dragin
  • dragout
  • drop

所有移动端支持的事件:

  • touchstart
  • touchmove
  • touchend
  • tap

支持链式调用.

/*
 * @cur: 当前图形.
 */
shape.on('mousedown', function( cur ) {
  console.log('you click rect');
}).on('mousemove', function( cur ) {
  console.log('you move!');
}).on('mouseleave', function( cur ) {
  console.log('you leave!');
}).drag(true).config(){...};

config

rect.config({
  zindex: 10,
  drag: true, // 图形开启拖拽
  changeIndex: true, // 当拖拽的时候,改变图形的顺序
  fixed: true, // 不受globalTranslate and globalScale 的影响。
});

Group

你可以把一些图形添加到一个组里,这样你可以让这些图形表现的行为一致。

const group = stage.group({
  x: 100,
  y: 100,
  width: 200,
  height: 200,
  title: {
    title: {
      text: 'Group Name',
      fontSize: 14,
      paddingTop: 12,
      paddingLeft: 14
    }
  },
  /**
   * @param {Object} background - 给组添加背景颜色
   */
  background: {
    color: '#000'
  },
  /**
   * @param {Object} border - 给组添加边框
   */
  border: {
    color: '#000',
  },
  zindex: 10
}).on('mousedown', function() {
  console.log('you clicked group');
});
  • 方法 group.add()

把图形添加到组里. 组内图形的坐标原点是组的 (x, y) 坐标。

  • 方法 group.remove()

从组内删除图形.

  1. remove([Array]) - 删除多个图形
  2. remove([Function]) - 删除的图形支持用filter过滤.
  • 方法 group.updateAllChildsPosition()

更新组内所有子图形的坐标位置。如果组的坐标发生了改变,需要调用这个函数来保证组内的图形跟随移动。

添加到待绘制列表.

group和图形一样,都需要addChild来添加到stage。

stage.addChild(rect);
stage.addChild(line);
stage.addChild(group);

// 或者

stage.addChild([rect, line, arc1, text1]);

从绘制列表移除.

stage.removeChild(rect);

stage.removeChild([rect, arc, line]);

stage.removeFirstChild();

stage.removeLastChild();

stage.removeAllChilds();

show()

绘制并且绑定事件.

stage.show();

如果你通过addChildremoveChild新增了某些图形和事件或者移除了某些图形和事件,那么你需要通过以下方法重置事件。

stage.show()

or

stage.draw();
stage._events.triggerEvents();

绘制和重绘

stage.draw();
stage.redraw();

重置

重置整个舞台,让所有图形的状态回归到初始值,会重置所有的拖拽位移和缩放.

stage.reset();

动画

全局动画

function go() {
  rect.x++;
  line.y = line.y + 2;
  arc.radius++;
}

stage.animate(go);

图形动画

在线示例

/**
 * @param: {keys | Object}   -- 动画结束时的值,是个对象
 * @param: {config | Object} -- 动画的一些配置项
 */
shape.animateTo({
  x: 100,
  y: 100,
  width: 200,
  height: 200
}, {
  duration: 1000, // 动画持续事件,默认 500 毫秒
  delay: 500, // 动画延迟的事件,默认 0 毫秒
  easing: 'bounceOut', // 动画的补间类型,默认 'linear' (匀速)
  onStart: function(keys) {
    /**
     * @param: keys
     * keys是一个对象,存放着图形运动到当前的一些坐标和内部数据。
     * same below
     */
    console.log(keys.x, keys.y, keys.width, keys.height);
  },
  onUpdate: function(keys) {
    console.log(keys.x, keys.y, keys.width, keys.height);
  },
  onFinish: function(keys) {
    console.log(keys.x, keys.y, keys.width, keys.height);
  },
});

补间动画类型

  • linear
  • quadIn
  • quadOut
  • quadInOut
  • cubicIn
  • cubicOut
  • cubicInOut
  • quartIn
  • quartOut
  • quartInOut
  • quintIn
  • quintOut
  • quintInOut
  • sineIn
  • sineOut
  • sineInOut
  • bounceOut
  • bounceIn
  • bounceInOut

清除动画

stage.clearAnimation();

finishAnimation

如果舞台上的所有动画都结束后,会调用这个方法。

stage.finishAnimation = () => {
  console.log('所有动画都结束了!');
};

自动缩放canvas

resize(opt)

  • opt.width {Function} -- 缩放后的宽度
  • opt.height {Function} -- 缩放后的高度
  • opt.resize {Function} -- 在缩放后触发的回调函数
world.resize({
  width: () => document.body.clientWidth,
  height: () => document.body.clientHeight,
  // 如果你传了resize, 需要调用update这个函数来更新canvas的尺寸。
  resize: (update) => {
    update();
  }
});

FPS (帧率)

fpsOn

当舞台上有动画的时候,你可以通过调用fpsOn来开启获取帧率。

stage.fpsOn(function(fps) {
  // fps即是帧率,每秒刷新一次
  console.log(fps);
});

关闭帧率获取

stage.fpsOff();

omg's People

Contributors

mgzu avatar pengjiyuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

omg's Issues

如果画单条直线,会报map没有定义

var line = stage.line({
    x: 10,
    y: 10,
    endX: 400,
    endY: 10
});

"Uncaught TypeError: Cannot read property 'map' of undefined"(1321行)

查看了源码看到是:

    this.scaled_matrix = this.matrix.map(function (m) { return m.map(function (n) { return n * scale; }); });

其中matrix没有定义。
本人比较渣看不太懂源码,望指导,谢谢。:no_mouth:

arc 渲染丢失

    // 圆的的数组
    var circles = [{ "name": "FW1-01", "type": 1, "x": 0.69, "y": 0.66 },
    { "name": "FW1-02", "type": 1, "x": 0.71, "y": 0.64 },
    { "name": "FW1-03", "type": 1, "x": 0.71, "y": 0.56 },
    { "name": "FW1-04", "type": 1, "x": 0.67, "y": 0.56 },
    { "name": "FW1-05", "type": 1, "x": 0.67, "y": 0.48 },
    { "name": "FW1-06", "type": 1, "x": 0.67, "y": 0.41 },
    { "name": "FW1-07", "type": 1, "x": 0.67, "y": 0.28 },
    { "name": "FW1-08", "type": 1, "x": 0.67, "y": 0.19 },
    { "name": "FW1-09", "type": 1, "x": 0.72, "y": 0.19 },
    { "name": "FW1-10", "type": 1, "x": 0.72, "y": 0.1 },
    { "name": "FW1-11", "type": 1, "x": 0.65, "y": 0.1 }];
// 圆点配置
    function createArc(circle) {
        let cirColor;
        switch (circle.type) {
            case 1:
                cirColor = "#330099";
                break;
            case 2:
                cirColor = "#00CCFF";
                break;
            case 3:
                cirColor = "#FFFF33";
                break;
            case 4:
                cirColor = "#993300";
                break;
            default:
                console.log("类型异常");
                throw new TypeError('TypeError in createArc');
        }
        const arc = stage.graphs.arc({
            x: (circle.x * stage.width).toFixed(1) + 100,
            y: (circle.y * stage.height).toFixed(1) + 100,
            radius: 5,
            color: cirColor,
            style: 'fill'
        }).on('mouseenter', function () {
            tip.style.display = 'block';
            setValue({
                title: '圆点信息',
                color: cirColor,
                name: circle.name,
                type: circle.type
            });
            stage.element.style.cursor = 'pointer';
            let x = stage.utils.getPos().x - 100;
            let y = stage.utils.getPos().y;
            tip.style.left = x + 'px';
            tip.style.top = y + 'px';
        }).on('mouseleave', function () {
            tip.style.display = 'none';// 隐藏tip
            stage.element.style.cursor = 'default';
        }).on('mousedown', function () {
            tip.style.display = 'none';
            document.getElementById("name").innerHTML = circle.name;
            document.getElementById("value").innerHTML = circle.value;
            $("#circlemodel").modal('show');
            currentArc = arc;
            currentCircle = circle;
        }).config({
            drag: false,
            changeIndex: false
        });
        stage.addChild(arc);
    }
    // 画圆
    function drawArc() {
        for (let i = 0; i < circles.length; i++) {
            createArc(circles[i]);
        }
    }

这里有11条数据数据,但是 canvas 渲染后只有5个点。@PengJiyuan
案例:https://serch.gitee.io/canvas-event/examples/canvas-event.html

当元素重叠时,设置圆drag为false时,圆仍可以移动

额,昨天发的邮件您可能没看到,我又来提issues啦,主要是对重叠元素的操作,详情在邮件中

  1. 将图片设置为背景,foreach数组,将圆添加到canvas中,config中drag设置为false,圆仍可以移动
  2. 给canvas或背景图片添加点击事件,这个会和圆的鼠标事件之间有冲突,这个对重叠的元素,怎样才能设置优先级,做到触发圆的事件时,不触发canvas或背景图片的点击事件呢

最后,望大佬丰富一下API文档(方法、参数等),源码咯的牙疼_(:з」∠)_

mouseenter,mouseleave 会闪个不停

需要在图片上移动上去加一层效果,类似http://3dcampus.lzjtu.edu.cn/

`

<title>Title</title>
您的浏览器不支持canvas,请升级浏览器,显示此行文本。
<script src="javascript/omg.js"></script> <script> const stage = omg({ element: document.getElementById('canvas'), width: 500, height: 500, enableGlobalTranslate: true, enableGlobalScale: true, position: 'absolute', // 改变canvas.style.position images: [], // 预加载的图片列表,通常不用指定,因为使用接口绘制图片的时候,会自动预加载。 prepareImage: true, // 是否开启预加载图片 }); // 在init之前,你可以通过`stage.extend(yourShape)`拓展自定义的图形。 stage.init(); const rect = stage.graphs.rectangle({ x: 0, y: 0, width: 200, height: 200, opacity:0.3, color: "rgba(0,0,0,0.4)" }); const image = stage.graphs.image({ x: 0, y: 0, width: 200, height: 200, src: './pics/2.png' }).on('mouseenter', function(cur) { stage.addChild(rect); stage.redraw(); }).on('mouseleave',function () { stage.removeChild(rect); stage.redraw(); }); stage.addChild(image); stage.show(); </script>

`

缩放不支持手机

很好用的一个canvas库,能否扩展下支持移动端的缩放。
谢谢。

添加缩放重置和背景图拖拽

  1. 需要一个缩放重置 api。目前我使用以下方法重置缩放,不知是否合适。
        stage.scale = 1;
        stage.redraw()
  1. init 后,暂未找到开启、关闭缩放的 api。
  2. 开启拖拽后,元素的移动可超出画布边界,这个是否有对应的 api ,使元素无法移出画布边界。
  3. 以下是我的配置,我想将 image 设置为背景图片且不可拖拽(fixed : true)。当使用缩放将画布放大时,却无法查看超出画布的背景图(fixed : false 也并不正确,背景图应当是无法移动的)。
    const stage = omg({
        element: document.getElementById('Canvas'),
        width: 750,
        height: 450,
        enableGlobalTranslate: true, // 开启全局拖拽
        enableGlobalScale: true, // 开启全局缩放
        position: 'absolute', // canvas.style.position
        prepareImage: true,
    });

    const image = stage.graphs.image({
        x: 0,
        y: 0,
        width: stage.width,
        height: stage.height,
        src: imgsrc,
        zindex: 0
    }).config({
        fixed: true
    });

渲染图形的鼠标事件触发存在问题

` //circle是一个对象,以下是circle的构造函数

  function Circle(x, y, radius, color, name, value, id) {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.color = color;
        this.name = name;
        this.value = value;
        this.id = id;
  }

  //初始化圆并添加到canvas中
  function createArc(circle) {
        var arc = world.arc({
            x: (circle.x*stage.width).toFixed(1),
            y: (circle.y*stage.height).toFixed(1),
            radius: circle.radius*10,
            color: circle.color,
            style: 'fill'
        }).on('mouseenter mousemove', function() {
            tip.style.display = 'block';
            setValue({
                title: '测点',
                color: circle.color,
                name: circle.name,
                value: circle.value,
            //  id: circle.id,
            });
            console.log(circle.value)
            world.element.style.cursor = 'pointer';
            var x = world.utils.getPos().x + 20;
            var y = world.utils.getPos().y + 20;
            tip.style.left = x + 'px';
            tip.style.top = y + 'px';
        }).on('mouseleave', function() {
            tip.style.display = 'none';//隐藏tip
            world.element.style.cursor = 'default';
        }).on('mousedown', function() {
            console.log('image3');
        }).config({
            drag: tr,
            changeIndex: false
        });
        stage.addChild(arc);
    }  `

以上是我的代码,想要达到的效果是,鼠标移入到圆上,在canvas中显示圆的信息(提示信息参考的是big_data的demo)。而测试的时候,发现当圆较小时,无法正确的触发鼠标事件,所以将圆的半径*10查看,当鼠标移入圆下半部分时还是无法触发,而鼠标事件的触发区域大概比正常区域提高了50px。
PS:第一次写lssuse,没有上传图片,望见谅

omg.js.org like landing page

Hi
I like you home page here: https://omg.js.org/
Currently, I have a project am working on and on the landing page, instead of the square and the triangles, I want to use, for example, medical tools images animated the way it is. How can I achieve this with OMG?

Thanks

touchend和mouseup事件都没有进入

var rect1 = this.stage.graphs.rectangle({
    x: 0,
    y: 0,
    width: txtW + 20,
    height: txtH + 20,
    radius: {
      tl: 6,
      tr: 6,
      bl: 6,
      br: 6
    },
    color: '#ef8376'
  }).on('mousedown', () => {
    this.stage.element.style.cursor = 'pointer';
    rect1.color = 'yellow';
    this.stage.redraw();
  }).on('mouseup', () => {
    console.log(788);//没有输出
    this.stage.element.style.cursor = 'default';
    rect1.color = '#ef8376';
    this.stage.redraw();
  });

鼠标移出canvas拖动图片位置显示异常

当指定canvas大小,canvas不铺满全屏时,鼠标移出canvas,图像会突然偏移很多,移入canvas图像又显示正常。尝试在移出时fixed或者全局禁用enableGlobalTranslate设为false,在鼠标未松开时仍不起作用。希望能够在移出后能够限制图像移动。

omg给自己节省了大量开发工作,简单易用,使用起来也非常方便,希望上面提到的这个问题能够解决下。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.