Skip to content

Commit

Permalink
feat: 新增横屏的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
zengyue committed Nov 19, 2020
1 parent d520485 commit 9eb85ca
Show file tree
Hide file tree
Showing 15 changed files with 303 additions and 72 deletions.
4 changes: 0 additions & 4 deletions examples/creative/apple/index.zh.md

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
172 changes: 172 additions & 0 deletions examples/creative/case/demo/landscape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import F2 from '@antv/f2';
import _ from 'lodash';
import insertCss from 'insert-css';

// 我们用 insert-css 演示引入自定义样式
// 推荐将样式添加到自己的样式文件中
// 若拷贝官方代码,别忘了 npm install insert-css
insertCss(`
.mobile-content {
height: 470px;
}
.container-wrap {
height: 375px;
width: 470px;
transform-origin: left top;
transform: translate(375px, 0) rotate(90deg);
}
#container {
height: 320px;
width: 470px;
}
.title-bar {
height: 50px;
width: 100%;
box-sizing: border-box;
padding: 0 16px;
border-bottom: 1px solid #E8E8E8;
display: flex;
justify-content: space-between;
}
.left-part {
display: flex;
align-items: center
}
.name {
color: #108EE9;
font-size: 16px;
}
.desc {
color: #999999;
font-size: 14px;
margin-left: 7px;
}
.right-part {
display: flex;
align-items: center;
padding-left: 40px;
}
.close {
position: relative;
width: 24px;
height: 24px;
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
}
.close::after, .close::before {
content: '';
height: 10px;
width: 2px;
background-color: #ffffff;
transform: rotate(45deg);
position: absolute;
top: 7px;
left: 11px;
}
.close::before {
transform: rotate(-45deg);
}
`);

document.querySelector('.mobile-content').innerHTML = `
<div class="container-wrap">
<div class="title-bar">
<div class="left-part">
<div class="name">这是一个横屏图</div>
<div class="desc">辅助性说明</div>
</div>
<div class="right-part">
<div class="close-wrap">
<div class="close"></div>
</div>
</div>
</div>
<canvas id="container" />
<div>
`;

fetch('https://gw.alipayobjects.com/os/antfincdn/OVMtvjbnut/series-line.json')
.then(res => res.json())
.then(data => {
const chart = new F2.Chart({
id: 'container',
pixelRatio: window.devicePixelRatio
});
chart.source(data);
chart.landscape(true);
chart.scale('date', {
range: [ 0, 1 ],
type: 'timeCat',
tickCount: 3
});
chart.scale('value', {
tickCount: 5
});
chart.axis('date', {
label: function label(text, index, total) {
// 只显示每一年的第一天
const textCfg = {
fill: '#ccc'
};
if (index === 0) {
textCfg.textAlign = 'left';
} else if (index === total - 1) {
textCfg.textAlign = 'right';
}
return textCfg;
}
});
chart.axis('value', {
label: {
fill: '#cccccc'
}
});
chart.legend({
nameStyle: {
fill: '#333333'
},
valueStyle: {
fill: '#e8541e'
}
});
chart.tooltip({
custom: true, // 自定义 tooltip 内容框
crosshairsStyle: {
stroke: '#108ee9',
lineDash: [ 4, 4 ]
},
onChange: function onChange(obj) {
const legend = chart.get('legendController').legends.top[0];
const tooltipItems = obj.items;
const legendItems = legend.items;
const map = {};
legendItems.forEach(function(item) {
map[item.name] = _.clone(item);
});
tooltipItems.forEach(function(item) {
const name = item.name;
const value = item.value;
if (map[name]) {
map[name].value = value;
}
});
legend.setItems(_.values(map));
},
onHide: function onHide() {
const legend = chart.get('legendController').legends.top[0];
legend.setItems(chart.getLegendItems().country);
}
});
chart.line()
.position('date*value')
.color('type', [ '#1677FF', '#00B7F4', '#FF9F18' ])
.size('type', [ 1.5, 1, 1 ]);
chart.area()
.position('date*value')
.color('type', [ 'l(90) 0:#1677ff 1:#FFFFFF', 'transparent', 'transparent' ]);

chart.render();
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
"filename": "steps-record.js",
"title": "健康步数",
"screenshot": "https://gw.alipayobjects.com/zos/rmsportal/MLIlBSbtaBRiivHdBGmM.png"
},
{
"filename": "landscape.js",
"title": "横屏图",
"screenshot": "https://gw.alipayobjects.com/zos/finxbff/compress-tinypng/18e3331d-b7bd-476e-93eb-f7a90fc55e00.png"
}
]
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
title: iOS Chart
title: gallery
order: 0
---
4 changes: 4 additions & 0 deletions examples/creative/case/index.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: 场景案例
order: 0
---
12 changes: 11 additions & 1 deletion src/chart/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ class Chart extends Base {
height: self.get('height'),
fontFamily: Global.fontFamily,
aria: self.get('aria'),
title: self.get('title')
title: self.get('title'),
landscape: self.get('landscape')
});
self.set('canvas', canvas);
self.set('el', canvas.get('el'));
Expand Down Expand Up @@ -919,6 +920,15 @@ class Chart extends Base {
plot.reset(start, end);
coord.reset(plot);
}
/**
* 是否为横屏展示
*
* @param {Boolean} landscape 是否为横屏
*/
landscape(landscape) {
const canvas = this.get('canvas');
canvas.set('landscape', landscape);
}
}

Chart.plugins = Chart.initPlugins();
Expand Down
29 changes: 1 addition & 28 deletions src/graphic/event/controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getRelativePosition } from '../../util/dom';
import { isNumber } from '../../util/common';
import { convertPoints } from '../../util/dom';

// 计算滑动的方向
const calcDirection = (start, end) => {
Expand All @@ -25,32 +24,6 @@ const getCenter = (point1, point2) => {
return { x, y };
};

const convertPoints = (ev, canvas) => {
const touches = ev.touches;
// 认为是mouse事件
if (!touches) {
const point = getRelativePosition({ x: ev.clientX, y: ev.clientY }, canvas);
return [ point ];
}
const points = [];
const len = touches.length;
for (let i = 0; i < len; i++) {
const touch = touches[i];
// x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
const { x, y, clientX, clientY } = touch;
let point;
// 小程序环境会有x,y
if (isNumber(x) || isNumber(y)) {
point = { x, y };
} else {
// 浏览器环境再计算下canvas的相对位置
point = getRelativePosition({ x: clientX, y: clientY }, canvas);
}
points.push(point);
}
return points;
};

const PRESS_DELAY = 250;

class EventController {
Expand Down
88 changes: 51 additions & 37 deletions src/util/dom.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isFunction, isNumber } from './common';

/**
* Detects support for options object argument in addEventListener.
* https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
Expand Down Expand Up @@ -80,19 +82,13 @@ function getDomById(id) {
function getRelativePosition(point, canvas) {
const canvasDom = canvas.get('el');
if (!canvasDom) return point;
const { top, right, bottom, left } = canvasDom.getBoundingClientRect();
const { top, left } = canvasDom.getBoundingClientRect();

const paddingLeft = parseFloat(getStyle(canvasDom, 'padding-left'));
const paddingTop = parseFloat(getStyle(canvasDom, 'padding-top'));
const paddingRight = parseFloat(getStyle(canvasDom, 'padding-right'));
const paddingBottom = parseFloat(getStyle(canvasDom, 'padding-bottom'));
const width = right - left - paddingLeft - paddingRight;
const height = bottom - top - paddingTop - paddingBottom;
const pixelRatio = canvas.get('pixelRatio');

const mouseX = (point.x - left - paddingLeft) / (width) * canvasDom.width / pixelRatio;
const mouseY = (point.y - top - paddingTop) / (height) * canvasDom.height / pixelRatio;

const mouseX = point.x - left - paddingLeft;
const mouseY = point.y - top - paddingTop;
return {
x: mouseX,
y: mouseY
Expand All @@ -107,41 +103,58 @@ function removeEventListener(source, type, listener) {
source.removeEventListener(type, listener, eventListenerOptions);
}

function createEventObj(type, chart, x, y, nativeEvent) {
return {
type,
chart,
native: nativeEvent || null,
x: x !== undefined ? x : null,
y: y !== undefined ? y : null
};
function landscapePoint(point, canvas) {
const landscape = canvas.get('landscape');
if (!landscape) {
return point;
}
if (isFunction(landscape)) {
return landscape(point, canvas);
}
// 默认顺时针旋转90度
const height = canvas.get('height');
const x = point.y;
const y = height - point.x;
return { x, y };
}

function createEvent(event, chart) {
const type = event.type;
let clientPoint;
// 说明是touch相关事件
if (event.touches) {
// https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent/changedTouches
// 这里直接拿changedTouches就可以了,不管是touchstart, touchmove, touchend changedTouches 都是有的
// 为了以防万一,做个空判断
const touch = event.changedTouches[0] || {};
function convertPoints(ev, canvas) {
const touches = ev.touches;
// 认为是mouse事件
if (!touches) {
const point = getRelativePosition({ x: ev.clientX, y: ev.clientY }, canvas);
return [ landscapePoint(point, canvas) ];
}
const points = [];
for (let i = 0, len = touches.length; i < len; i++) {
const touch = touches[i];
// x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
const { x, y, clientX, clientY } = touch;
// 小程序环境会有x,y,这里就直接返回
if (x && y) {
return createEventObj(type, chart, x, y, event);
let point;
// 小程序环境会有x,y
if (isNumber(x) || isNumber(y)) {
point = { x, y };
} else {
// 浏览器环境再计算下canvas的相对位置
point = getRelativePosition({ x: clientX, y: clientY }, canvas);
}
clientPoint = { x: clientX, y: clientY };
} else {
// mouse相关事件
clientPoint = { x: event.clientX, y: event.clientY };
points.push(landscapePoint(point, canvas));
}
// 理论上应该是只有有在浏览器环境才会走到这里
return points;
}

function createEvent(event, chart) {
const canvas = chart.get('canvas');
// 通过clientX, clientY 计算x, y
const point = getRelativePosition(clientPoint, canvas);
return createEventObj(type, chart, point.x, point.y, event);
const points = convertPoints(event, canvas);
// touchend会没有points
const point = points[0] || {};
return {
type: event.type,
chart,
native: event,
x: point.x,
y: point.y
};
}

function measureText(text, font, ctx) {
Expand All @@ -168,5 +181,6 @@ export {
addEventListener,
removeEventListener,
createEvent,
convertPoints,
measureText
};
2 changes: 1 addition & 1 deletion test/fixtures/canvas-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ canvas.style.width = '370px';
canvas.style.height = '300px';
document.body.appendChild(canvas);

describe('svg 渲染', () => {
describe('默认渲染', () => {
it('render', () => {
const data = [
{ genre: 'Sports', sold: 275 },
Expand Down
Loading

0 comments on commit 9eb85ca

Please sign in to comment.