feat: 1.新增 ButtonControl 基类 2.完成 Fullscreen UI 开发

This commit is contained in:
yanxiong 2022-08-10 20:52:02 +08:00
parent 7c401b8a25
commit c636dc7684
27 changed files with 1317 additions and 269 deletions

View File

@ -10,10 +10,10 @@
"browser": true,
"node": true
},
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module"
},
// "parser": "babel-eslint",
// "parserOptions": {
// "sourceType": "module"
// },
"plugins": [
"html"
],

View File

@ -0,0 +1,6 @@
---
title: 全屏
order: 8
---
<code src="./fullscreen.tsx" compact defaultShowCode></code>

View File

@ -0,0 +1,61 @@
import {
GaodeMap,
PositionType,
Scene,
Fullscreen,
createL7Icon,
} from '@antv/l7';
import React, { useState } from 'react';
// tslint:disable-next-line:no-duplicate-imports
import { FunctionComponent, useEffect } from 'react';
const POSITION_LIST = Object.values(PositionType);
const Demo: FunctionComponent = () => {
const [fullscreen, setFullscreen] = useState<Fullscreen | null>(null);
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new GaodeMap({
style: 'dark',
center: [120, 30],
pitch: 0,
zoom: 6.45,
}),
// logoVisible: false,
});
scene.on('loaded', () => {
const newFullscreen = new Fullscreen();
setFullscreen(newFullscreen);
scene.addControl(newFullscreen);
});
}, []);
return (
<>
<button
onClick={() => {
const flag = Math.random() > 0.5;
fullscreen?.setOptions({
position: flag ? 'topleft' : 'topright',
icon: flag ? createL7Icon('l7-icon-quanping') : undefined,
text: !flag ? '全屏' : undefined,
});
}}
>
options
</button>
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
</>
);
};
export default Demo;

View File

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

View File

@ -0,0 +1,211 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>iconfont Demo</title>
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
<style>
.main .logo {
margin-top: 0;
height: auto;
}
.main .logo a {
display: flex;
align-items: center;
}
.main .logo .sub-title {
margin-left: 0.5em;
font-size: 22px;
color: #fff;
background: linear-gradient(-45deg, #3967FF, #B500FE);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=3580659" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon l7-iconfont">&#xe655;</span>
<div class="name">全屏</div>
<div class="code-name">&amp;#xe655;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持两种方式引用多色图标SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'l7-iconfont';
src: url('iconfont.woff2?t=1660133611296') format('woff2'),
url('iconfont.woff?t=1660133611296') format('woff'),
url('iconfont.ttf?t=1660133611296') format('truetype');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.l7-iconfont {
font-family: "l7-iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="l7-iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"l7-iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon l7-iconfont l7-icon-quanping"></span>
<div class="name">
全屏
</div>
<div class="code-name">.l7-icon-quanping
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="l7-iconfont l7-icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
l7-iconfont" 是你项目下的 font-family。可以通过编辑项目查看默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#l7-icon-quanping"></use>
</svg>
<div class="name">全屏</div>
<div class="code-name">#l7-icon-quanping</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

View File

@ -0,0 +1,19 @@
@font-face {
font-family: "l7-iconfont"; /* Project id 3580659 */
src: url('iconfont.woff2?t=1660133611296') format('woff2'),
url('iconfont.woff?t=1660133611296') format('woff'),
url('iconfont.ttf?t=1660133611296') format('truetype');
}
.l7-iconfont {
font-family: "l7-iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.l7-icon-quanping:before {
content: "\e655";
}

View File

@ -0,0 +1 @@
!function(e){var t,n,o,a,i,d='<svg><symbol id="l7-icon-quanping" viewBox="0 0 1024 1024"><path d="M85.333333 682.666667v128a128 128 0 0 0 128 128h128a42.666667 42.666667 0 0 0 0-85.333334H213.333333a42.666667 42.666667 0 0 1-42.666666-42.666666v-128a42.666667 42.666667 0 0 0-85.333334 0z m597.333334 256h128a128 128 0 0 0 128-128v-128a42.666667 42.666667 0 0 0-85.333334 0v128a42.666667 42.666667 0 0 1-42.666666 42.666666h-128a42.666667 42.666667 0 0 0 0 85.333334z m256-597.333334V213.333333a128 128 0 0 0-128-128h-128a42.666667 42.666667 0 0 0 0 85.333334h128a42.666667 42.666667 0 0 1 42.666666 42.666666v128a42.666667 42.666667 0 0 0 85.333334 0zM341.333333 85.333333H213.333333a128 128 0 0 0-128 128v128a42.666667 42.666667 0 0 0 85.333334 0V213.333333a42.666667 42.666667 0 0 1 42.666666-42.666666h128a42.666667 42.666667 0 0 0 0-85.333334z" ></path></symbol></svg>',c=(c=document.getElementsByTagName("script"))[c.length-1].getAttribute("data-injectcss"),l=function(e,t){t.parentNode.insertBefore(e,t)};if(c&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(e){console&&console.log(e)}}function s(){i||(i=!0,o())}function r(){try{a.documentElement.doScroll("left")}catch(e){return void setTimeout(r,50)}s()}t=function(){var e,t=document.createElement("div");t.innerHTML=d,d=null,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(e=document.body).firstChild?l(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),t()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(o=t,a=e.document,i=!1,r(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,s())})}(window);

View File

@ -0,0 +1,16 @@
{
"id": "3580659",
"name": "L7",
"font_family": "l7-iconfont",
"css_prefix_text": "l7-icon-",
"description": "",
"glyphs": [
{
"icon_id": "12323755",
"name": "全屏",
"font_class": "quanping",
"unicode": "e655",
"unicode_decimal": 58965
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,90 @@
import { DOM } from '@antv/l7-utils';
import { IButtonControlOption } from '../../interface';
import Control from './control';
export { ButtonControl };
export default abstract class ButtonControl extends Control<
IButtonControlOption
> {
/**
*
* @protected
*/
protected isDisable = false;
protected textContainer?: HTMLElement;
protected iconContainer?: HTMLElement;
// constructor(option?: Partial<IButtonControlOption>) {
// super(option);
// }
public abstract onClick(e: MouseEvent): void;
public setIsDisable(newIsDisable: boolean) {
this.isDisable = newIsDisable;
if (newIsDisable) {
this.container.setAttribute('disabled', 'true');
} else {
this.container.removeAttribute('disabled');
}
}
public onAdd(): HTMLElement {
const button = DOM.create('button', 'l7-button-control') as HTMLElement;
button.addEventListener('click', this.onClick.bind(this));
return button;
}
// tslint:disable-next-line:no-empty
public onRemove(): void {}
public setOptions(newOptions: Partial<IButtonControlOption>) {
const { title, text, icon } = newOptions;
if ('title' in newOptions) {
this.container.setAttribute('title', title ?? '');
}
if ('icon' in newOptions) {
this.updateButtonIcon(icon);
}
if ('text' in newOptions) {
this.updateButtonText(text);
}
super.setOptions(newOptions);
}
protected updateButtonText(newText: IButtonControlOption['text']) {
if (newText) {
let textContainer = this.textContainer;
if (!textContainer) {
textContainer = DOM.create(
'div',
'l7-button-control__text',
) as HTMLElement;
this.container.appendChild(textContainer);
this.textContainer = textContainer;
}
textContainer.innerText = newText;
} else if (!newText && this.textContainer) {
DOM.remove(this.textContainer);
this.textContainer = undefined;
}
}
protected updateButtonIcon(newIcon: IButtonControlOption['icon']) {
if (this.iconContainer) {
DOM.remove(this.iconContainer);
}
if (newIcon) {
const firstChild = this.container.firstChild;
if (firstChild) {
this.container.insertBefore(newIcon, firstChild);
} else {
this.container.appendChild(newIcon);
}
this.iconContainer = newIcon;
}
}
}

View File

@ -0,0 +1,258 @@
import {
IControlOption,
IControlService,
ILayerService,
IMapService,
IRendererService,
ISceneService,
PositionName,
PositionType,
TYPES,
} from '@antv/l7-core';
import { DOM } from '@antv/l7-utils';
import EventEmitter from 'eventemitter3';
import { Container } from 'inversify';
import { ControlEvent } from '../../interface';
export { PositionType } from '@antv/l7-core';
export { Control };
export default abstract class Control<
O extends IControlOption = IControlOption
> extends EventEmitter<ControlEvent> {
/**
*
* @protected
*/
protected static controlCount = 0;
/**
*
*/
public controlOption: O;
/**
* DOM
* @protected
*/
protected container: HTMLElement;
/**
*
* @protected
*/
protected isShow: boolean;
protected sceneContainer: Container;
protected scene: ISceneService;
protected mapsService: IMapService;
protected renderService: IRendererService;
protected layerService: ILayerService;
protected controlService: IControlService;
constructor(option?: Partial<IControlOption>) {
super();
Control.controlCount++;
this.controlOption = {
...this.getDefault(),
...(option || {}),
};
}
/**
*
* @param newOptions
*/
public setOptions(newOptions: Partial<O>): void {
const {
position: oldPosition,
className: oldClassName,
style: oldStyle,
} = this.controlOption;
if ('position' in newOptions && newOptions.position !== oldPosition) {
this.setPosition(newOptions.position);
}
if ('className' in newOptions && newOptions.className !== oldClassName) {
this.setContainerClassName(newOptions.className);
}
if ('style' in newOptions && newOptions.style !== oldStyle) {
this.setContainerStyle(newOptions.style);
}
this.controlOption = {
...this.controlOption,
...newOptions,
};
}
/**
* Control Scene controlService
* @param sceneContainer
*/
public addTo(sceneContainer: Container) {
// 初始化各个 Service 实例
this.mapsService = sceneContainer.get<IMapService>(TYPES.IMapService);
this.renderService = sceneContainer.get<IRendererService>(
TYPES.IRendererService,
);
this.layerService = sceneContainer.get<ILayerService>(TYPES.ILayerService);
this.controlService = sceneContainer.get<IControlService>(
TYPES.IControlService,
);
this.scene = sceneContainer.get<ISceneService>(TYPES.ISceneService);
this.sceneContainer = sceneContainer;
this.isShow = true;
// 初始化 container
this.container = this.onAdd();
DOM.addClass(this.container, 'l7-control');
// 将 container 插入容器中
this.insertContainer();
this.setOptions(this.controlOption);
this.emit('add', this);
return this;
}
/**
*
*/
public remove() {
if (!this.mapsService) {
return this;
}
DOM.remove(this.container);
this.onRemove();
this.emit('remove', this);
}
/**
* Control Control DOM
*/
public abstract onAdd(): HTMLElement;
/**
* Control
*/
public abstract onRemove(): void;
/**
*
*/
public show() {
const container = this.container;
DOM.removeClass(container, 'l7-control-hide');
this.isShow = true;
this.emit('show', this);
}
/**
*
*/
public hide() {
const container = this.container;
DOM.addClass(container, 'l7-control-hide');
this.isShow = false;
this.emit('hide', this);
}
/**
*
*/
public getDefault(): O {
// tslint:disable-next-line:no-object-literal-type-assertion
return {
position: PositionType.TOPRIGHT,
name: `${Control.controlCount}`,
} as O;
}
/**
* DOM
*/
public getContainer() {
return this.container;
}
/**
* Control
*/
public getIsShow() {
return this.isShow;
}
public _refocusOnMap(e: MouseEvent) {
// if map exists and event is not a keyboard event
if (this.mapsService && e && e.screenX > 0 && e.screenY > 0) {
const container = this.mapsService.getContainer();
if (container !== null) {
container.focus();
}
}
}
/**
*
* @param position
*/
protected setPosition(
position: PositionType | PositionName = PositionType.TOPLEFT,
) {
// 考虑组件的自动布局,需要销毁重建
const controlService = this.controlService;
if (controlService) {
controlService.removeControl(this);
}
this.controlOption.position = position;
if (controlService) {
controlService.addControl(this, this.sceneContainer);
}
return this;
}
/**
* container className
* @param className
*/
protected setContainerClassName(className?: string | null) {
const container = this.container;
const { className: oldClassName } = this.controlOption;
if (oldClassName) {
DOM.removeClass(container, oldClassName);
}
if (className) {
DOM.addClass(container, className);
}
}
/**
* container style
* @param style
*/
protected setContainerStyle(style?: string | null) {
const container = this.container;
const { style: oldStyle } = this.controlOption;
if (oldStyle) {
DOM.removeStyle(container, oldStyle);
}
if (style) {
DOM.addStyle(container, style);
}
}
/**
* DOM position
* @protected
*/
protected insertContainer() {
const container = this.container;
const position = this.controlOption.position;
const corner = this.controlService.controlCorners[position];
if (position.indexOf('bottom') !== -1) {
corner.insertBefore(container, corner.firstChild);
} else {
corner.appendChild(container);
}
}
}

View File

@ -1,256 +1,2 @@
import {
IControlOption,
IControlService,
ILayerService,
IMapService,
IRendererService,
PositionName,
PositionType,
TYPES,
} from '@antv/l7-core';
import { DOM } from '@antv/l7-utils';
import EventEmitter from 'eventemitter3';
import { Container } from 'inversify';
export { PositionType } from '@antv/l7-core';
export type ControlEvent = 'show' | 'hide' | 'add' | 'remove' | string;
export default abstract class Control<
O extends IControlOption = IControlOption
> extends EventEmitter<ControlEvent> {
/**
*
* @protected
*/
protected static controlCount = 0;
/**
*
*/
public controlOption: O;
/**
* DOM
* @protected
*/
protected container: HTMLElement;
/**
*
* @protected
*/
protected isShow: boolean;
protected sceneContainer: Container;
protected mapsService: IMapService;
protected renderService: IRendererService;
protected layerService: ILayerService;
protected controlService: IControlService;
constructor(option?: Partial<IControlOption>) {
super();
Control.controlCount++;
this.controlOption = {
...this.getDefault(),
...(option || {}),
};
}
/**
*
* @param newOptions
*/
public setOptions(newOptions: Partial<O>): void {
const {
position: oldPosition,
className: oldClassName,
style: oldStyle,
} = this.controlOption;
if ('position' in newOptions && newOptions.position !== oldPosition) {
this.setPosition(newOptions.position);
}
if ('className' in newOptions && newOptions.className !== oldClassName) {
this.setContainerClassName(newOptions.className);
}
if ('style' in newOptions && newOptions.style !== oldStyle) {
this.setContainerStyle(newOptions.style);
}
this.controlOption = {
...this.controlOption,
...newOptions,
};
}
/**
* Control Scene controlService
* @param sceneContainer
*/
public addTo(sceneContainer: Container) {
// 初始化各个 Service 实例
this.mapsService = sceneContainer.get<IMapService>(TYPES.IMapService);
this.renderService = sceneContainer.get<IRendererService>(
TYPES.IRendererService,
);
this.layerService = sceneContainer.get<ILayerService>(TYPES.ILayerService);
this.controlService = sceneContainer.get<IControlService>(
TYPES.IControlService,
);
this.sceneContainer = sceneContainer;
this.isShow = true;
// 初始化 container
this.container = this.onAdd();
DOM.addClass(this.container, 'l7-control');
const { className, style } = this.controlOption;
this.setContainerClassName(className);
this.setContainerStyle(style);
// 将 container 插入容器中
this.insertContainer();
this.emit('add', this);
return this;
}
/**
*
*/
public remove() {
if (!this.mapsService) {
return this;
}
DOM.remove(this.container);
this.onRemove();
this.emit('remove', this);
}
/**
* Control Control DOM
*/
public abstract onAdd(): HTMLElement;
/**
* Control
*/
public abstract onRemove(): void;
/**
*
*/
public show() {
const container = this.container;
DOM.removeClass(container, 'l7-control-hide');
this.isShow = true;
this.emit('show', this);
}
/**
*
*/
public hide() {
const container = this.container;
DOM.addClass(container, 'l7-control-hide');
this.isShow = false;
this.emit('hide', this);
}
/**
*
*/
public getDefault(): O {
// tslint:disable-next-line:no-object-literal-type-assertion
return {
position: PositionType.TOPRIGHT,
name: `${Control.controlCount}`,
} as O;
}
/**
* DOM
*/
public getContainer() {
return this.container;
}
/**
* Control
*/
public getIsShow() {
return this.isShow;
}
public _refocusOnMap(e: MouseEvent) {
// if map exists and event is not a keyboard event
if (this.mapsService && e && e.screenX > 0 && e.screenY > 0) {
const container = this.mapsService.getContainer();
if (container !== null) {
container.focus();
}
}
}
/**
*
* @param position
*/
protected setPosition(
position: PositionType | PositionName = PositionType.TOPLEFT,
) {
// 考虑组件的自动布局,需要销毁重建
const controlService = this.controlService;
if (controlService) {
controlService.removeControl(this);
}
this.controlOption.position = position;
if (controlService) {
controlService.addControl(this, this.sceneContainer);
}
return this;
}
/**
* container className
* @param className
*/
protected setContainerClassName(className?: string | null) {
const container = this.container;
const { className: oldClassName } = this.controlOption;
if (oldClassName) {
DOM.removeClass(container, oldClassName);
}
if (className) {
DOM.addClass(container, className);
}
}
/**
* container style
* @param style
*/
protected setContainerStyle(style?: string | null) {
const container = this.container;
const { style: oldStyle } = this.controlOption;
if (oldStyle) {
DOM.removeStyle(container, oldStyle);
}
if (style) {
DOM.addStyle(container, style);
}
}
/**
* DOM position
* @protected
*/
protected insertContainer() {
const container = this.container;
const position = this.controlOption.position;
const corner = this.controlService.controlCorners[position];
if (position.indexOf('bottom') !== -1) {
corner.insertBefore(container, corner.firstChild);
} else {
corner.appendChild(container);
}
}
}
export { Control, PositionType } from './control';
export { ButtonControl } from './buttonControl';

View File

@ -0,0 +1,27 @@
import { IButtonControlOption } from '../interface';
import { createL7Icon } from '../utils/icon';
import ButtonControl from './baseControl/buttonControl';
export default class Fullscreen extends ButtonControl {
protected isFullscreen = false;
get mapContainer() {
return 1;
}
public onClick(e: MouseEvent): void {
// if (this.isFullscreen) {
//
// } else {
//
// }
}
public getDefault(): IButtonControlOption {
return {
...super.getDefault(),
icon: createL7Icon('l7-icon-quanping'),
title: '全屏',
};
}
}

View File

@ -1,7 +1,7 @@
import { IControlOption, PositionType } from '@antv/l7-core';
import { bindAll, DOM } from '@antv/l7-utils';
import { ILayerControlOption } from '../interface';
import Control from './baseControl';
import { Control } from './baseControl';
interface IInputItem extends HTMLInputElement {
layerId: string;

View File

@ -1,6 +1,6 @@
import { IControlOption } from '@antv/l7-core';
import { DOM } from '@antv/l7-utils';
import Control, { PositionType } from './baseControl';
import { Control, PositionType } from './baseControl';
export default class Logo extends Control {
public getDefault() {

View File

@ -1,6 +1,6 @@
import { bindAll, DOM, lnglatDistance } from '@antv/l7-utils';
import { IScaleControlOption } from '../interface';
import Control, { PositionType } from './baseControl';
import { Control, PositionType } from './baseControl';
export default class Scale extends Control {
private mScale: HTMLElement;

View File

@ -1,6 +1,6 @@
import { bindAll, DOM } from '@antv/l7-utils';
import { IZoomControlOption } from '../interface';
import Control, { PositionType } from './baseControl';
import { Control, PositionType } from './baseControl';
export default class Zoom extends Control {
private disabled: boolean;

View File

@ -0,0 +1,25 @@
@import 'variables.less';
.l7-button-control {
min-width: @l7-btn-control-size;
height: @l7-btn-control-size;
background-color: @l7-control-bg-color;
border-width: 0;
border-radius: @l7-btn-control-border-radius;
outline: 0;
cursor: pointer;
transition: background-color 0.2s;
display: flex;
justify-content: center;
align-items: center;
&:hover {
background-color: @l7-btn-control-bg-hover-color;
}
&:active {
background-color: @l7-btn-control-bg-active-color;
}
* + .l7-button-control__text {
margin-left: 4px;
}
}

View File

@ -10,6 +10,7 @@
z-index: 800;
float: left;
clear: both;
font-size: @l7-control-font-size;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;

View File

@ -1,3 +1,5 @@
@import './variables.less';
@import './l7.less';
@import './baseControl.less';
@import 'variables';
@import 'l7';
@import 'control';
@import 'buttonControl';
@import '../assets/iconfont.css';

View File

@ -1 +1,8 @@
@l7-control-space: 10px;
@l7-control-font-size: 12px;
@l7-control-bg-color: #fff;
@l7-btn-control-bg-color: @l7-control-bg-color;
@l7-btn-control-bg-hover-color: darken(@l7-control-bg-color, 10%);
@l7-btn-control-bg-active-color: darken(@l7-control-bg-color, 15%);
@l7-btn-control-size: 30px;
@l7-btn-control-border-radius: 2px;

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with Vectornator (http://vectornator.io/) -->
<svg height="100%" stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 682.67 682.67" width="100%" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<clipPath id="ArtboardFrame">
<rect height="682.67" width="682.67" x="0" y="0"/>
</clipPath>
<g clip-path="url(#ArtboardFrame)" id="Untitled" vectornator:layerName="Untitled">
<path d="M0 477.87L0 580.27C0.00552233 636.822 45.8483 682.664 102.4 682.67L204.8 682.67C223.424 682.351 238.356 667.162 238.356 648.535C238.356 629.908 223.424 614.719 204.8 614.4L102.4 614.4C83.5505 614.4 68.27 599.119 68.27 580.27L68.27 477.87C68.4812 465.535 62.0216 454.046 51.3734 447.817C40.7252 441.588 27.5448 441.588 16.8966 447.817C6.24842 454.046-0.211108 465.535 0 477.87ZM477.87 682.67L580.27 682.67C636.822 682.664 682.664 636.822 682.67 580.27L682.67 477.87C682.881 465.535 676.422 454.046 665.773 447.817C655.125 441.588 641.945 441.588 631.297 447.817C620.648 454.046 614.189 465.535 614.4 477.87L614.4 580.27C614.4 599.119 599.119 614.4 580.27 614.4L477.87 614.4C465.535 614.189 454.046 620.648 447.817 631.297C441.588 641.945 441.588 655.125 447.817 665.773C454.046 676.422 465.535 682.881 477.87 682.67ZM682.67 204.8L682.67 102.4C682.664 45.8483 636.822 0.00553344 580.27 1.15748e-06L477.87 1.15748e-06C465.535-0.211139 454.046 6.24838 447.817 16.8966C441.588 27.5448 441.588 40.7252 447.817 51.3734C454.046 62.0216 465.535 68.4811 477.87 68.27L580.27 68.27C599.119 68.27 614.4 83.5505 614.4 102.4L614.4 204.8C614.719 223.424 629.908 238.356 648.535 238.356C667.162 238.356 682.351 223.424 682.67 204.8ZM204.8 0L102.4 0C45.8483 0.00551165 0.00552271 45.8483-3.66902e-07 102.4L-3.66902e-07 204.8C0.318807 223.424 15.5078 238.356 34.135 238.356C52.7622 238.356 67.9512 223.424 68.27 204.8L68.27 102.4C68.27 83.5505 83.5505 68.27 102.4 68.27L204.8 68.27C223.424 67.9512 238.356 52.7622 238.356 34.135C238.356 15.5078 223.424 0.318804 204.8 0Z" fill="#333333" fill-rule="nonzero" opacity="1" stroke="none"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,4 +1,5 @@
import Control from './control/baseControl';
import { ButtonControl, Control } from './control/baseControl';
import Fullscreen from './control/fullscreen';
import Layers from './control/layer';
import Logo from './control/logo';
import Scale from './control/scale';
@ -6,11 +7,24 @@ import Zoom from './control/zoom';
import Marker from './marker';
import MarkerLayer from './marker-layer';
import Popup from './popup';
import { createL7Icon } from './utils/icon';
// 引入样式
// TODO: 使用 Less 或者 Sass每个组件单独引用自身样式
import './css/index.less';
export { Control, Logo, Scale, Zoom, Layers, Marker, Popup, MarkerLayer };
export {
Control,
ButtonControl,
Logo,
Scale,
Zoom,
Layers,
Marker,
Popup,
MarkerLayer,
Fullscreen,
createL7Icon,
};
export * from './interface';

View File

@ -1,5 +1,13 @@
import { IControlOption } from '@antv/l7-core';
export type ControlEvent = 'show' | 'hide' | 'add' | 'remove' | string;
export interface IButtonControlOption extends IControlOption {
icon?: HTMLElement;
text?: string;
title?: string;
}
export interface ILayerControlOption extends IControlOption {
collapsed: boolean;
autoZIndex: boolean;

View File

@ -0,0 +1,5 @@
import { DOM } from '@antv/l7-utils';
export const createL7Icon = (className: string) => {
return DOM.create('i', `l7-iconfont ${className}`);
};