From f43ea41badddf86d2c1c3bd94e0c33e7c793ee75 Mon Sep 17 00:00:00 2001 From: chenyonghang Date: Fri, 21 Jun 2024 19:12:10 +0800 Subject: [PATCH] 5 --- src/Basic-information.html | 1299 - src/Houduan/index.js | 51 - src/Houduan/index1.js | 1793 - src/Qianduan/Backend-services/frame.html | 428 - src/Qianduan/Load/Load.html | 180 - src/Qianduan/Load/bei.jpg | Bin 714783 -> 0 bytes src/Qianduan/Load/load.css | 261 - .../Basic-information-1.html | 1006 - .../Basic-information/Basic-information.html | 1299 - .../Cardiovascular-system-drugs.html | 288 - .../Dermatological-medication.html | 289 - .../Digestive-system-drugs.html | 288 - .../Export-information/Export-information.css | 159 - .../Export-information.html | 91 - src/Qianduan/src/Home-page/Home-page.html | 339 - .../Import-information/Import-information.css | 189 - .../Import-information.html | 606 - .../Income-statistics/Income-statistics.css | 204 - .../Income-statistics/Income-statistics.html | 83 - .../Information-statistics.html | 1465 - .../src/Information-statistics/echarts.js | 57027 ---------------- .../Ophthalmic-medication.html | 289 - .../Orthopedic-medication.html | 288 - .../Outbound-statistics.html | 293 - .../Respiratory-system-medication.html | 287 - 25 files changed, 68502 deletions(-) delete mode 100644 src/Basic-information.html delete mode 100644 src/Houduan/index.js delete mode 100644 src/Houduan/index1.js delete mode 100644 src/Qianduan/Backend-services/frame.html delete mode 100644 src/Qianduan/Load/Load.html delete mode 100644 src/Qianduan/Load/bei.jpg delete mode 100644 src/Qianduan/Load/load.css delete mode 100644 src/Qianduan/src/Basic-information/Basic-information-1.html delete mode 100644 src/Qianduan/src/Basic-information/Basic-information.html delete mode 100644 src/Qianduan/src/Cardiovascular-system-drugs/Cardiovascular-system-drugs.html delete mode 100644 src/Qianduan/src/Dermatological-medication/Dermatological-medication.html delete mode 100644 src/Qianduan/src/Digestive-system-drugs/Digestive-system-drugs.html delete mode 100644 src/Qianduan/src/Export-information/Export-information.css delete mode 100644 src/Qianduan/src/Export-information/Export-information.html delete mode 100644 src/Qianduan/src/Home-page/Home-page.html delete mode 100644 src/Qianduan/src/Import-information/Import-information.css delete mode 100644 src/Qianduan/src/Import-information/Import-information.html delete mode 100644 src/Qianduan/src/Income-statistics/Income-statistics.css delete mode 100644 src/Qianduan/src/Income-statistics/Income-statistics.html delete mode 100644 src/Qianduan/src/Information-statistics/Information-statistics.html delete mode 100644 src/Qianduan/src/Information-statistics/echarts.js delete mode 100644 src/Qianduan/src/Ophthalmic-medication/Ophthalmic-medication.html delete mode 100644 src/Qianduan/src/Orthopedic-medication/Orthopedic-medication.html delete mode 100644 src/Qianduan/src/Outbound-statistics/Outbound-statistics.html delete mode 100644 src/Qianduan/src/Respiratory-system-medication/Respiratory-system-medication.html diff --git a/src/Basic-information.html b/src/Basic-information.html deleted file mode 100644 index 92dcb9f..0000000 --- a/src/Basic-information.html +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - 药品基本信息 - - - - - - - - - -

- - - - - - - - - - -

- - - -

-
- - -
-

- - - - - - - - - - - -

- - - - - - - - - - - -

- - - - - - - -

- - - - - - - - - - - - -

- - - - - - - - - - -
序号类型药名价格库存
- - - - - - \ No newline at end of file diff --git a/src/Houduan/index.js b/src/Houduan/index.js deleted file mode 100644 index cb881ae..0000000 --- a/src/Houduan/index.js +++ /dev/null @@ -1,51 +0,0 @@ -const express = require('express'); -const app = express(); -const mysql = require('mysql'); - -function dj(){ - -} -// 创建连接对象 -const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 -}); - -// 开启连接 -connection.connect(); - -var asd=' '; -// 执行查询 -connection.query('Select * from 药品;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - asd = results; - console.log(results); -}); - -// 关闭连接 -connection.end(); - -app.use((req, res, next) => { - res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500'); // 替换为您的前端应用域名 - res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); - res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); - res.setHeader('Access-Control-Allow-Credentials', true); - next(); -}); - -app.get('/', (req, res) => { - - res.send(asd); - - console.log("hello") -}); - - -const PORT = 3000; -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); -}); - diff --git a/src/Houduan/index1.js b/src/Houduan/index1.js deleted file mode 100644 index 36691d0..0000000 --- a/src/Houduan/index1.js +++ /dev/null @@ -1,1793 +0,0 @@ -const express = require('express'); -const app = express(); -const mysql = require('mysql'); -const fs = require('fs'); -const { exec } = require('child_process'); -const http = require('http'); -const querystring = require('querystring'); - -function dj(){ - -} - -function arrayToCsv(data) { - return data.map(row => row.map(field => { - // 如果 field 不是字符串,先转换为字符串 - const strField = field.toString(); - // 然后进行替换操作 - return `"${strField.replace(/"/g, '""')}"`; - }).join(',')).join('\n'); -} - -// 创建连接对象 -const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 -}); - -// 开启连接 -connection.connect(); - -var asd=' '; -// 执行查询 -connection.query('Select * from 账户;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - asd = results; - console.log(results); -}); - -// 关闭连接 -connection.end(); - -app.use((req, res, next) => { - res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500'); // 替换为您的前端应用域名 - res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); - res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); - res.setHeader("Content-Security-Policy", "default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'") - - res.setHeader('Access-Control-Allow-Credentials', true); - next(); -}); - -//登录账户 -app.get('/', (req, res) => { - if (req.method === 'POST'){ - - }else{ - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - connection.query('Select * from 账户;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - asd = results; - res.send(asd); - }); - connection.end(); - } -}); - - -app.post('/', (req, res) => { - if (req.method === 'POST'){ - console.log("ssssssssss"); - let body = ''; - req.on('data', chunk => { - - body += chunk.toString(); // 转换为字符串 - }); - req.on('end', () => { - // 解析POST参数 - - console.log(body); - - const postParams = JSON.parse(body); - // 处理POST参数 - console.log('POST parameters:', postParams); - var abc = ' '; - - //注册账户 - if (postParams.wenti == 0){ - console.log("注册账户。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('insert into 账户 values ("'+String(postParams.用户名)+'","'+String(postParams.密码)+'")'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = {"账户注册情况":'成功',"用户名":String(postParams.用户名),"密码":String(postParams.密码)}; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询药库 - if (postParams.wenti == 1){ - console.log("查询药库。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 主页面 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查找药品 - if (postParams.wenti ==2){ - console.log("查找药品。"); - // console.log(postParams); - // var as = String(postParams.id); - // console.log(as); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - var sortnum = 0; - findid1=''; - if (postParams.id!=null){ - //console.log(postParams.id); - findid1+=' where id = '; - findid1+=String(postParams.id); - sortnum++; - } - findtype1=''; - if (postParams.type!=null){ - //console.log(postParams.type); - if (sortnum!=0){ - findtype1+=' and '; - findtype1+=' type like '; - findtype1+='"%'+String(postParams.type)+'%"'; - sortnum++; - console.log(findtype1); - } - else{ - findtype1+=' where type like '; - findtype1+='"%'+String(postParams.type)+'%"'; - sortnum++; - } - } - findname1=''; - if(postParams.name!=null){ - //console.log(postParams.name); - if (sortnum!=0){ - findname1+=' and '; - findname1+=' name like '; - findname1+='"%'+String(postParams.name)+'%"'; - sortnum++; - } - else{ - findname1+=' where name like '; - findname1+='"%'+String(postParams.name)+'%"'; - sortnum++; - } - - } - findprice1=''; - if (postParams.price!=null){ - //console.log(postParams.price); - if (sortnum!=0){ - findprice1+=' and '; - findprice1+=' price = '; - findprice1+=String(postParams.price); - sortnum++; - } - else{ - findprice1+=' where price = '; - findprice1+=String(postParams.price); - sortnum++; - } - } - findamount1=''; - if (postParams.amount!=null){ - if (sortnum!=0){ - findamount1+=' and '; - findamount1+=' amount ='; - findamount1+=String(postParams.amount); - sortnum++; - } - else{ - findamount1+=' where amount = '; - findamount1+=String(postParams.amount); - sortnum++; - } - } - // connection.connect(); - connection.query('Select * from 主页面'+findid1+findtype1+findname1+findprice1+findamount1+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - - } - - //修改药品信息 - if (postParams.wenti ==3){ - console.log("修改药品信息。"); - console.log(postParams); - const currentTime = new Date(); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - if (postParams.type==null && postParams.name==null && postParams.price==null && postParams.amount==null ){ - console.log('没有说明要修改的字段'); - } - else{ - - //修改主页面药品信息 - sortnum2=0; - findid2 = ''; - findid2 = String(postParams.id); - findtype2 = ''; - if (postParams.type != null){ - findtype2 += ' type = '; - findtype2 += ' "'+String(postParams.type)+'" '; - sortnum2++; - } - findname2 = ''; - if (postParams.name != null){ - if (sortnum2 == 0){ - findname2 += 'name ='; - findname2 += ' "'+String(postParams.name)+'" '; - sortnum2++; - } - else{ - findname2 += ' , '; - findname2 += 'name ='; - findname2 += ' "'+String(postParams.name)+'" '; - sortnum2++; - } - } - findprice2 = ''; - if (postParams.price != null){ - if (sortnum2 == 0){ - findprice2 += 'price = '; - findprice2 += ' '+String(postParams.price)+' '; - sortnum2++; - } - else{ - findprice2 += ' , '; - findprice2 += 'price = '; - findprice2 += ' '+String(postParams.price)+' '; - sortnum2++; - } - } - findamount2 = ''; - if (postParams.amount != null){ - if (sortnum2 == 0){ - findamount2 += 'amount = '; - findamount2 += ' '+String(postParams.amount)+' '; - sortnum2++; - } - else{ - findamount2 += ' , '; - findamount2 += 'amount = '; - findamount2 += ' '+String(postParams.amount)+' '; - sortnum2++; - } - } - - //修改具体药品类型表 - - var sortnum21 = 0; - findname21 = ''; - if (postParams.name != null){ - if (sortnum21 == 0){ - findname21 += 'name ='; - findname21 += ' "'+String(postParams.name)+'" '; - sortnum21++; - } - else{ - findname21 += ' , '; - findname21 += 'name ='; - findname21 += ' "'+String(postParams.name)+'" '; - sortnum21++; - } - } - findprice21= ''; - if (postParams.price != null){ - if (sortnum21 == 0){ - findprice21 += 'price = '; - findprice21 += ' '+String(postParams.price)+' '; - sortnum21++; - } - else{ - findprice21 += ' , '; - findprice21 += 'price = '; - findprice21 += ' '+String(postParams.price)+' '; - sortnum21++; - } - } - findamount21 = ''; - if (postParams.amount != null){ - if (sortnum21 == 0){ - findamount21 += 'amount = '; - findamount21 += ' '+String(postParams.amount)+' '; - sortnum21++; - } - else{ - findamount21 += ' , '; - findamount21 += 'amount = '; - findamount21 += ' '+String(postParams.amount)+' '; - sortnum21++; - } - } - - //如果数量发生变化,自动生成出库或进库记录 - - if (postParams.amount != postParams.amounted){ - console.log(postParams.amount - postParams.amounted); - if (postParams.amount > postParams.amounted){//添加进库药品统计 - console.log('insert into 进库药品统计 (name,company,phonenumber,price,purprice) select name,company,phonenumber,price,purprice from ' + String(postParams.type) + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) +';'); - console.log(' update 进库药品统计 set amount = ' + String(postParams.amount - postParams.amounted) + ' , '+ 'time = ' + '"' + currentTime.toLocaleString()+ '" ' + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) + ' and time is NULL and amount is NULL'+';'); - - connection.query('insert into 进库药品统计 (name,company,phonenumber,price,purprice) select name,company,phonenumber,price,purprice from ' + String(postParams.type) + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) +';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query(' update 进库药品统计 set amount = ' + String(postParams.amount - postParams.amounted) + ' , '+ 'time = ' + '"' + currentTime.toLocaleString()+ '" ' + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) + ' and time is NULL and amount is NULL'+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - } - else if (postParams.amount < postParams.amounted){//添加出库药品统计 - console.log('insert into 出库药品统计 (name,company,phonenumber,price,purprice) select name,company,phonenumber,price,purprice from ' + String(postParams.type) + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) +';'); - console.log(' update 出库药品统计 set amount = ' + String(postParams.amounted - postParams.amount) + ' , '+ 'time = ' + '"' + currentTime.toLocaleString()+ '" ' + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) + ' and time is NULL and amount is NULL'+';'); - - connection.query('insert into 出库药品统计 (name,company,phonenumber,price,purprice) select name,company,phonenumber,price,purprice from ' + String(postParams.type) + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) +';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query(' update 出库药品统计 set amount = ' + String(postParams.amounted - postParams.amount) + ' , '+ 'time = ' + '"' + currentTime.toLocaleString()+ '" ' + ' where name = ' + '"' + String(postParams.nameed) + '"' + ' and price = ' + String(postParams.priceed) + ' and time is NULL and amount is NULL'+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - } - } - - - - - //执行数据库操作 - - console.log(' update '+ String(postParams.type) + ' set ' + findname21 + findprice21 + findamount21 + ' where name = "' + String(postParams.nameed) + '" and price = ' + String(postParams.priceed) + ';'); - console.log(' update 主页面 set ' + findtype2 + findname2 + findprice2 + findamount2 +' where id = '+findid2+';'); - if (sortnum2 != 0){ - connection.query(' update 主页面 set ' + findtype2 + findname2 + findprice2 + findamount2 +' where id = '+findid2+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query(' update '+ String(postParams.type) + ' set ' + findname21 + findprice21 + findamount21 + ' where name = "' + String(postParams.nameed) + '" and price = ' + String(postParams.priceed) + ';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - } - - } - connection.query('Select * from 主页面 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - //console.log(results.length) - }); - connection.end(); - } - - //删除药品 - if (postParams.wenti ==4){ - console.log("删除药品。"); - console.log(postParams); - const currentTime = new Date(); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - sortnum3 = 0; - - if (postParams.id == null){ - console.log('没有待删除的药品的序号'); - } - else{ - findid3 = ' where id = '; - if (postParams.id != null){ - findid3 += String(postParams.id); - findid3 += ' '; - sortnum3++; - } - findname3 = ''; - if (postParams.name != null){ - if (sortnum3 != 0){ - findname3 += ' and '; - findname3 += ' name = '; - findname3 += ' "'; - findname3 += String(postParams.name); - findname3 += '" '; - } - } - - findtype3 = String(postParams.type); - findname31 = ' where name = '; - findname31 += ' "'; - findname31 += String(postParams.name); - findname31 += '" '; - findprice3 = 'and price = '; - findprice3 += parseFloat(postParams.price); - findtime3 = '"' + currentTime.toLocaleString()+ '"'; - - // console.log('delete from '+ findtype3 + findname31 + findprice3+';'); - - // console.log('insert into 出库药品统计 (name,company,phonenumber,amount,price) select * from ' + findtype3 + findname31 + findprice3+';'); - - // console.log('update 出库药品统计 set time = ' + findtime3 + findname31 + findprice3+';'); - - connection.query('insert into 出库药品统计 (name,company,phonenumber,amount,price,purprice) select name,company,phonenumber,amount,price,purprice from ' + findtype3 + findname31 + findprice3+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query('update 出库药品统计 set time = ' + findtime3 + findname31 + findprice3+ ' and time is NULL' +';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query('delete from '+ findtype3 + findname31 + findprice3+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query(' delete from 主页面 ' + findid3 + findname3+';', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - - } - - connection.query('Select * from 主页面 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - //console.log(results.length) - }); - connection.end(); - } - - //添加药品 - if (postParams.wenti == 5){ - - console.log("添加药品。"); - console.log(postParams); - const currentTime = new Date(); - //console.log((currentTime.toLocaleString())); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - findid4 = String(postParams.id); - findtype4 = '"' + String(postParams.type)+ '"'; - findtype41 = String(postParams.type); - findname4 = '"' + String(postParams.name)+ '"'; - findprice4 = String(postParams.price); - findpurprice4 = String(postParams.purprice); - findamount4 = String(postParams.amount); - findcompany4 = '"' + String(postParams.company)+ '"'; - findphonenumber4 = '"' + String(postParams.phonenumber)+ '"'; - findtime4 = '"' + currentTime.toLocaleString()+ '"'; - - //console.log(' insert into 主页面 values ('+ findid4 + ',' + findtype4 + ',' + findname4 + ',' + findprice4 + ',' + findamount4 +');'); - //console.log(' insert into '+findtype41+' values ('+ findname4 + ',' + findcompany4 + ',' + findphonenumber4 + ',' + findprice4 + ',' + findamount4 +');'); - connection.query(' insert into 主页面 values ('+ findid4 + ',' + findtype4 + ',' + findname4 + ',' + findprice4 + ',' + findamount4 +');', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - connection.query(' insert into '+findtype41+' values ('+ findname4 + ',' + findcompany4 + ',' + findphonenumber4 + ',' + findprice4 + ',' + findamount4 +','+ findpurprice4+');', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - - connection.query(' insert into '+'进库药品统计'+' values ('+ findname4 + ',' + findcompany4 + ',' + findphonenumber4 + ',' + findamount4 + ',' + findprice4 + ',' + findpurprice4 + ',' +findtime4+');', (error, results, fields) => { - if (error) throw error; - //console.log(results); - // 处理查询结果 - }); - - - - - - connection.query('Select * from 主页面 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - - } - - //查询呼吸系统药 - if (postParams.wenti == 11){ - console.log("查询呼吸系统药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 呼吸系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询消化系统药 - if (postParams.wenti == 21){ - console.log("查询消化系统药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 消化系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询皮肤科用药 - if (postParams.wenti == 31){ - console.log("查询皮肤科用药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 皮肤科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询心血管系统药 - if (postParams.wenti == 41){ - console.log("查询心血管系统药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 心血管系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询眼科用药 - if (postParams.wenti == 51){ - console.log("查询眼科用药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 眼科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询骨科用药 - if (postParams.wenti == 61){ - console.log("查询骨科用药。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 骨科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询出库药品统计 - if (postParams.wenti == 71){ - console.log("查询出库药品统计。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 出库药品统计 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //查询进库药品统计 - if (postParams.wenti == 81){ - console.log("查询进库药品统计。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select * from 进库药品统计 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - //导入csv数据 - if (postParams.wenti==1001){ - - - //导入数据到主页面 - if (postParams.table == '主页面'){ - console.log(postParams.table); - console.log(postParams); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到骨科用药 - if (postParams.table == '骨科用药'){ - console.log(postParams.table); - console.log(postParams); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到眼科用药 - if (postParams.table == '眼科用药'){ - console.log(postParams.table); - console.log(postParams); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到皮肤科用药 - if (postParams.table == '皮肤科用药'){ - console.log(postParams.table); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到呼吸系统药 - if (postParams.table == '呼吸系统药'){ - console.log(postParams.table); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到消化系统药 - if (postParams.table == '消化系统药'){ - console.log(postParams.table); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到心血管系统药 - if (postParams.table == '心血管系统药'){ - console.log(postParams.table); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到进库药品统计 - if (postParams.table == '进库药品统计'){ - console.log(postParams.table); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - //导入数据到出库药品统计 - if (postParams.table == '出库药品统计'){ - console.log(postParams.table); - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - for (i =0;i { - if (error) throw error; - console.log(results); - }); - - } - - } - connection.end(); - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - } - - } - - //导出csv数据 - if (postParams.wenti==1002){ - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - connection.query('Select * from 主页面;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["id","type","name","price","amount"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 眼科用药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 骨科用药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 皮肤科用药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 呼吸系统药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 消化系统药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 心血管系统药;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 出库药品统计;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","amount","price","purprice","time"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('Select * from 进库药品统计;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["name","company","phonenumber","amount","price","purprice","time"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - - connection.query('select 主页面.id ,主页面.type,主页面.name,眼科用药.company,眼科用药.phonenumber,眼科用药.price,眼科用药.amount,眼科用药.purprice from 主页面,眼科用药 where 主页面.name = 眼科用药.name and 主页面.price = 眼科用药.price union all select 主页面.id ,主页面.type,主页面.name,骨科用药.company,骨科用药.phonenumber,骨科用药.price,骨科用药.amount,骨科用药.purprice from 主页面,骨科用药 where 主页面.name = 骨科用药.name and 主页面.price = 骨科用药.price union all select 主页面.id ,主页面.type,主页面.name,皮肤科用药.company,皮肤科用药.phonenumber,皮肤科用药.price,皮肤科用药.amount,皮肤科用药.purprice from 主页面,皮肤科用药 where 主页面.name = 皮肤科用药.name and 主页面.price = 皮肤科用药.price union all select 主页面.id ,主页面.type,主页面.name,呼吸系统药.company,呼吸系统药.phonenumber,呼吸系统药.price,呼吸系统药.amount,呼吸系统药.purprice from 主页面,呼吸系统药 where 主页面.name = 呼吸系统药.name and 主页面.price = 呼吸系统药.price union all select 主页面.id ,主页面.type,主页面.name,消化系统药.company,消化系统药.phonenumber,消化系统药.price,消化系统药.amount,消化系统药.purprice from 主页面,消化系统药 where 主页面.name = 消化系统药.name and 主页面.price = 消化系统药.price union all select 主页面.id ,主页面.type,主页面.name,心血管系统药.company,心血管系统药.phonenumber,心血管系统药.price,心血管系统药.amount,心血管系统药.purprice from 主页面,心血管系统药 where 主页面.name = 心血管系统药.name and 主页面.price = 心血管系统药.price order by id;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - var shuju = results; - var csvData = []; - csvData.push(["id","type","name","company","phonenumber","price","amount","purprice"]); - for (i=0;i { - if (err) throw err; - console.log('CSV 文件已被保存到:', filePath); - }); - }); - //关闭连接 - connection.end(); - - var abc = ' '; - abc = '已经收到并处理完消息'; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - - const command = "explorer D:\\迁移"; - - exec(command, (error, stdout, stderr) => { - - }); - - } - - if (postParams.wenti == 20011){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 骨科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20012){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 皮肤科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20013){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 眼科用药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20014){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 呼吸系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20015){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 消化系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20016){ - console.log("药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('Select name,amount from 心血管系统药 '+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20021){ - console.log("出库药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round((price-purprice)*amount,2) AS value from 出库药品统计;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20022){ - console.log("出库药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round((price-purprice)*amount,2) AS value from 出库药品统计 where time like '+'"%'+String(postParams.data)+'%"'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20023){ - console.log("出库药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select name from 出库药品统计'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20024){ - console.log("出库药品数量统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round((price-purprice)*amount,2) AS value from 出库药品统计 where name like '+'"%'+String(postParams.data)+'%"'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20031){ - console.log("药品支出统计分析。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round(purprice*amount,2) AS value from 进库药品统计;', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20032){ - console.log("药品支出统计。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round(purprice*amount,2) AS value from 进库药品统计 where time like '+'"%'+String(postParams.data)+'%"'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20033){ - console.log("药品支出统计。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select name from 进库药品统计'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - if (postParams.wenti == 20034){ - console.log("药品支出统计。"); - console.log(postParams); - - const connection = mysql.createConnection({ - host: 'localhost', // 数据库服务器地址 - user: 'root', // 数据库用户名 - password: 'CYH123456', // 数据库密码 - database: 'cyh1' // 要连接的数据库名 - }); - connection.connect(); - - - connection.query('select left(time,9) AS name,round(purprice*amount,2) AS value from 进库药品统计 where name like '+'"%'+String(postParams.data)+'%"'+';', (error, results, fields) => { - if (error) throw error; - // 处理查询结果 - abc = results; - res.writeHead(200, {'Content-Type': 'application/json'}); - const responseData = abc ; - // 发送响应数据 - res.end(JSON.stringify(responseData)); - //console.log(JSON.stringify(responseData)); - }); - connection.end(); - } - - - - // res.writeHead(200, {'Content-Type': 'application/json'}); - // const responseData = {name:'POST request received'} ; - // // 发送响应数据 - // res.end(JSON.stringify(responseData)); - // console.log(JSON.stringify(responseData)); - }); - } -}); - - -const PORT = 3000; -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); -}); - diff --git a/src/Qianduan/Backend-services/frame.html b/src/Qianduan/Backend-services/frame.html deleted file mode 100644 index 990b471..0000000 --- a/src/Qianduan/Backend-services/frame.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - - 药品管理系统 - - - - - - -
-
-

- -

- - -

- - - - - - - - -

- - - -

- - - -

- - - -

- - - -

- - - -
-
-
-

药品管理系统〉首页

-
-
- -
-
-
- - - - - \ No newline at end of file diff --git a/src/Qianduan/Load/Load.html b/src/Qianduan/Load/Load.html deleted file mode 100644 index 1358469..0000000 --- a/src/Qianduan/Load/Load.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - 登录界面 - -

药品管理系统

-

请登录您的账号

- - - - -
-

登录

-

-
- - - - -
-

-
- - - - -
-

- - -

没有账号?点击注册!

- -
- - - - - - - - - - - - \ No newline at end of file diff --git a/src/Qianduan/Load/bei.jpg b/src/Qianduan/Load/bei.jpg deleted file mode 100644 index 54ab62f781983802a7b07b3fc9fe5dd1bac421bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 714783 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 !{Jl`pG%Kw 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%0Av7gX@hW4oQ`s&;~w8HBnC=wNdS|8&5RO8 zaq|(#80nv(B#}n%U%;gF+WxOw-@dy&Z)#k|(@X!kZUTOzr= zu)T?*dyW84vfiPO$d|Sya~bMWj8-N~5r6dWz}z3ei1 zQY?UmYeTj6XDl)Z3{(Nqc8dNoXP$HiR zRAXsQQfkYuyBNyKPSbknW7VOCqf!&yPBG?klW~M%nr*!~q}*=eu9H@K=zSlh>smIp zg|vNNP1M2yS#0iMmP8%*M66kRWaEzh`rAQFjjhfI+D_d1rlwlDK#$<>~mE2c273h8#)O>lWYAv zwX@1~wu;{HY7SgQ3&N=@OB<66vTV6nT&t{wcDn8;;^jL+r70?xv*lM^b>Bs%t+uVU zx)WasPB)!8pSxT8Nm^fJD=Rl9-RzgVl1V7S@)3p10n0&oqCwpg=3oA#a&!@<-+e(cg zDCMWyhRGpv$JC)>%7scWBoJX`bZq|s8nP0Fa5yT=FisCj>8DZ6$v8MTyDPNZmq}SR z(r-n5`W$s>s3^G2Pn%YhWVvLTR&B0U(t4=2`Zag0wr9uyCS$N@!k+z4vq^=Zt5k zUUT?zN#>p-Y=9NBj@Tbwq-WP3%y0{Jx?i8%H7jnpw02tb^Lj5WY^~fp)k3>tCmiy4 z0G>GM*Ph^X#bEf0NVf4EiPP^0NLqNN+#-e8h=~PMOpd4|R%K#=T&oo)YcieF3*%^w zjx)|d^&}IVAJ2}SqMo+SagabHXXjp{B=8$O2Lm1b&Iv*;EjF5auIsg#Jnc)FZnm}7 zt8I2(tL9+o+H5*aly+9FF@_>UVrd#*Ee=0+n~4h=oy?J_RRx%Z=Csas@_GOZa58(g z1~Gxj?f6!Zw}=D3k)C)Y^NxT0SvmKpXSIenkl!Sw4_Ac_=E^tlpgPu^(MqQ6Ww++cEf1cT~3*DvCj;-1)9Znm|yy$x$_ z#tG%Un)UF}m_@WRNfdD}GR*rCLoP`qRLWeja<|KEdp_N@Mv$e=J9EV=_1D$;^?sit zZQ1x9TVps}ZU^sRcF5#*{5oQ*w4yE~D;a(e%0yxD$p~8;hya`n@yg=>*PQW6HtLhqs(@PN4A)kJsVP@>Z&$~rddx0If-q9tkyw`HZs;O>ED%T(4txsIiCbqNI zHH&q5admGrCgCPaWR@@{m6j7Fv)m+`VL+_m9mLBQ-K-ubk~gUiR;-`B7M1q*z16R7 z?#-LW4bL{I)W7nyoFyi{CZX@z%I#}+6{o$T_jQqaGsh&KTIfx?J6p>BN#6I{@%bFmQH|qt-M4A)s@BQtb$xp4 zv3XxVH<)wC1&c2|eq0bZ!*kqcIn6<+>ItS=O@DK6BDR1jmPsVY`IszWa>sKsHq}rv zdFlbIJy%fFG{uffT{i1d^O>Vmh2z?+sPd>{WG;1A?V_L0@)g(e%l`lZXFK+3Y-}3SNP^1IV7Bt~Qj3Qo>f-Mtm6E-bQ{L;| zw((lH#XIeWqX|O4wy3U@Dn`(9n{vE)=Gv3IlZsr;r&6lrjO)rOEx+-Wrgc??p4;sD zqg+angxx$^a)kgk0|9X~(ITU;!j@7oy9Xyk(r&Kowf_JT>IUacwz!$?ueAV%Tg1^7 zj8j-?ThGs_-6|VWO5*tq-0M^@b-(KM`0$jf2L0QuZbX#LM2v)?)uV8yI~Z1 zHM)crahA99Wq2c5#2I#zVaf08v`ctrmf}LQ3v?FgU|Lx;%L{0ie39GQG>ruJd)ds_ zvZRwqId}6hfmp_b>a{A9=32@z*74?E>z0Y_cV%m-G^Cfj`zm9o;gh9@qwJ)VDb%SX zlbfeB>PDKpqi$swbJV-kXqR;lcD%;Pr13Yv0@V6PO*gj#*6}2Q-|e@TGO|Y;1jj47 zlFD4i<-50*OO!&j>6d;Pu0BaH6&faNo zs~l*mfF1(Hd|72{dn^fkZELFA%Xg?;BnQm6)1w6sl`9z@-o>N93W>dmRsaqw(IN4y z+TV#IS#%g0^jp2nh`9z;i88`VnU%{&XKiW}IEe&LC(I=*M;^PS-!0-qWQk*q;t2t0 z<4?9mi@A(8#X_yHRV7nki9i8Bz{M&Q>rK?BIYliOENq;Wlap#MChAm-nvA692&DxrwS3hs+@hY)y7})%(!56>r9UMt@O)XU4GH8LmS;(YZ0_i zO&x}u8dXKOnn@iQRwHk0NEwudC)V{(2I*Sfv1P03Yc=C(mc}bxK1rC^A$CS-n%M|f zW(cTKP4O@TC`y7hq0%fZ?-uq8G>&A6Vu?bZCe?Q{5ov7sg4vw0CQEqZV#JcfgIY%j z;MJtpEtF*D+i|kKkxDR4>Z2ce*HV&A-x}GHoLc18tX!u}Q&EpUJk%{I%B1SbFlkDq zMxdKgjXTB`z=>`zAiuYPF0Jk3{{W9GJL#0kHRM^HA-kBs!DC6|2h5E~bzB7-s5}Y?y;+Vz2r$y!XlO?wG!;!*0L?e#GQy#X{3r_vNaLK7Uw6qVY#p};AE0XATRKe z0pkY*fzXkh_}`J(lcN>@o4CrpCJOqWa2VT#f*8?a{$A!#ILGfy}&M zK{yH#0;1Hg)Mvb79gJUTg4q!s@xnzKv=Z~VLY z;hOUcZUpAuI4uwanpvJB8-8+AH(^B=K?5Y^6&@Giv(1+%W0#TLzLQxMnCwXCxJdJ?_aGt_F8V0j>v9@dt_K z@g&gMPi=E9k8Na^5?vvCbduUNx+~>E@gFjK%ZrAJGjO|sQ6uaMYiq_j_u2KEi9kk)r8f843NKeH z9+eo=qfQOcjOtWVP;#`Bm7_UHq@(UpqN0-Cb!7D9rsO{RMoVuCSon6qMbC(J``an* zH4Ds{Bh)n+5`9weMU%2vteWhkA&M%3o5KKWL|oZu-)hk8ns{cg)86Va3~@w`(E$t1 zcePkcBg-J%49JnE%n3Oadj9~!*Os0uv(?1%Tj_dMn>DpeF*1CPmwDY4EitARk0#7O{nb`fYG^yWwvTTw# z97YVglpq%EO}nmFWlkw-+DltCeL0(Qo6)q=zf9rHSu4%dTHHcd>Pu;4pYbZNvD4#;Vz-fo=nkABjZ)s!pDJfrCR8sovwEho_EN(Y zjnpyTH1Z-rX7Q!Ow^ugn_L$x{N|5hw!#_NVj1miWOXKa|VI zFEHA*)R)%rO(vgnGs>?BNF%woo&-g=kk2G<8Z=6RNA2P8t)pu3c%Q`@WvBMtmA%c? zzMF2XJ*}mpl#MR6hh}>_o7YqFw93gEAxOgFKz1%Q?Gnn)+fccwriOc7XHsjHWoJW zC}|_Sk`eYxR%8(eW|T)I>mZDIOEV1cjq`@9;%#5W7nbd-%p_!y#4Q3eX%uV}x*#s# z#+y_j+8mZ*%tp{UzZGkj*HI>|eJod38nzxAd-S)GG_kzg9|e zyM*Mfl8RAy+I_91)}kX#SlFh(uQl9%yG^(yeBd0bxH-7g%haTWVYF>hNbSY3 zUp)Pi4oeB-^Cg9gw1z+=Q*kEsZO9cu?GnX%B1LQ>B^~CJjmV1XxQc9#pK$=JWN$g+ z8LTPP_G;0EIm%0!xkbsPc{Gx4>gg#rqiS7jk=t7i>d%^WaTMVRI%+iQMm*9=3Qlu` zS2E^ugcMx4Tx8QuPTxUV+;~dkO`7k){u8!+a>gmX#c4IKo4qo4Uf$kBiKJ&bZ1&^Kw}2@RBWh5yk>;+`h|guId^7OsDoQ+WYp3m0 zcT24qo_NH&l@{RJ>W>ong&2ijyNt69z#k!4?`&=Ebjxw}X{4Cj>L}LnrObgO-jD+- zeWC^4in758kIlh~P{_=t)Dmi1G+W2)ji>PBk3T%{rLGw^Cf`t*6-D!{$k)-ijg(~M%Ts+F5} zm9|`U{HdVIF+rfLqc%XT-JFH+gkUAFgIypay& zUF~bOSdKF5xogetkBS!lKN5I>ZZws=(ii(8(PNt47SZ0_ZD5wcq#kK|?;)f&4DTfJ zyUt{9GjZNZg*M?B%A}Q>=GHXtd(GLn=#p`6@@=&nE8muz##W4K)RjCuT%~BnHmhFt zwJ6@xQM+nTNk$2CR8nn4a#Cs1YF7z)cQkey8qF=Pmju%@`2sEbB9hz|-4F}q%P^59 zyO^r(j7Vi)dhq^%apIi{D+sZp_+Hy+5ZGJBHEn)qg9jgKm0CMHFl5`kp}CZn18@oR zb3PvUZ>Z}}YpnRU?7Aj~i1+PevBhn1Bs&X6Wr{G3X$)z~2MHq}+DigK_2c4e%U=)N zYCatB)&2gTZsx;Ag38JKyQpGNuYQp%W@%$*kOh$mNtqb@#xsk<(dAO9IJm}fyG=`; zaY^pAai*5gTEBHAWoM2*7VCRDSb0LFN;6UCQjf8tQOe0ie(Wk@A1vJJ%b7>slJ}(C ze7D4!1&4<$wJl#;n@q60wy}>%@OOhW>7=-uPJq0-ukLjK@HG0KpzhaKGQFy;y2~7K zE205j2?f+gP`bF*Y~;VSG0nQwCGr!0mdR+oYb2#@?WSm*kx;aVhBjp_xM+BwYhzTF z>s`0HwZ6WYuEo9cx@uw~?HZe? zWM&^M2Z1S88IUGhXktk@HRso=r8JZr6kM$tE4gU(sG3?^l_=RpG3Adf+rPVnp(=Ex zIo6EjRuPP)2{pG^V;_YH}g2K+~JBg=jcKbVDO(BvkIta@BoOvtdgKHufQWGBNz$Dj2 zI+3E3Ar(@z?CMHN$`P`Y)kjDq*KTdwvPt>)npJUfb!s_K!cvo1c)`iksW$l`D>r%7 zl&<2_mn1ZT)=hf%i9A7h7NoY?W{D&^43JyiK@H}f%N6mF641(GQV3P+ZtsK^cTbL;*p_{Vvx z>GA3DYYJ>Hn&{pAmM9~=`yggE*7tKXWs&X(iLO!;8b*Q8B4-ulww8AGSijYxxqHWT zxYP7^iK2(dazbhs)5tRMyM;?g<8^77W_J<@S8QTu8j^~H+^qSzno)%|*Dd2~sV&rX z=59@>w|Op%x}31^a;-)*+lzvvoTobLo0+L|rDo)!>NW1DrOhP=7)onhIvZ#pp7={V zmr$Fqsd0BCt9`oI#v_{R3bQ9MAc13L48STX4=AxgKbT77n!jtMd8Luk8#Xqnd15XD zNpbVX=SD5xCNzx@nWeszG(srfY>LHALV~(b_+z!xQoXv~`@7w?pRSClRB=wFX4I$e zCZwEHY?E-&MM*`*$_mX{rmtfn-s1O8xOr{Cjz|5|syZ~@QOn4nvTX~9(3VvU2*}SO zv^9HuLLqN)cWLBX-rL1KoiuWNrU_A$Nb|`#Bh0yti!AD5i(@HGxB;5HUQgN>NQ-jl z0v1^?U5P(3%&odYtU3oJfgi()wVBbL&0)A?^F)@`B*;=LnUQ?P`#wT`{Ns2kOu*(% z;EEDyIJ?^Z>b{H5?%6A9y57L&6*x5*-6!oNKd)Eh{IzVr0sKXmhwt*%Gt-{zuF~b%N5@ef(cd_0J3X0w}?SDW0hQ&ibKk|3%6#% zLlp;ea0$p67&WrG2D@~zTiICZcMHuA=qmt-YKClUdeaziwLi6ql-|p)7JLV+YqDN zFPm*~cu`rTF`RE$q++`R6+)$3&27THcf;Nh*R`Y<`i#xtg}Wk4gtvk*dv|cd26c^bxRIMjcq@0qnyIQ1@R%=A8(@M*2-(~a3$lZcLBjx$CkXY^*0OOIt?NJsi;4dei znU5{g1ExoQ_{gQ(xb%F2Lmj-4>_Ge3z`^PcJJZ4yIUo~}$p<6bj-H1c6M@O9@2QpV zbsMzguDT_3-iq5rZm+7cy48hCZY&hA0OR;U0|0Fu_TcU$%o zIKa+9ILYU}Y5xEy=OIZ4IXLP%Hgl4FNa5j*6=Zgd6UeN)=kR8=JLp80P@6| z&<=Lmao!6&_m(}S?YBF`?(zKyFN)M7sn!Ac=(|44m z%AY(JGK%-SvrpBpbVY|+MoI6lVw%%Rmi{(tD@)b+eAy7Xtn3gxMm0o^*T4NKTncPdsMxRj;E;FsfIU@fYL3zWHOLh(liQRYC|bunE(;%-X6ZyG``D>)bbLQ^q-pol9bZhp(ItY; zICN_bR?V8;J)UFTPo&wHf=@h$$v0Chaufmp3Wg!Fge66|DvB|bRixuDcIx#n%#?2V zY`LV}t+P5RRHs@BZi|$oIXOl$ji%!+N>Ec*mnw@+N)U`?XVoTf9}oWk;V8KA7N{-C z*xWp6b3D3*yq9s<5j+ z+@h#PAz4!htO}ax^xZw|0tJo`0udmOEGC_p7n(_@GEVLHwyBV!s~xI1#`Gzu#aeEn zZcxLiEyUh* zmV5lfCIbF?@&PFj_f2dC;p{lR;ba$7NY4>X#)ONRjWVTqg#vp?B z;qB!n*;{nC1|;8yXjQU;M)V177ILOpXCNQClS={;yyFovZt6D!k&JE!H86z$P!SX! zp%GMIdhGxfIKbm9dgnPixZNdtE8k1EqrY2QRd;)?mN_FO2hV3F*D6+NCe)L> zC3vY``kZz3w}|z7OY26K+eSAr{hB+3-*-A%%mBOq<^@S6P4Pz{QW0b)W^q?EUkh64 zaLF57OLAp~C>`4om5w~0E;64oqcaw9l3O{*B-c_Hm&V;?$)=pzpH839OV??xnoWH&MQXRN->kYSd6)7Q$@*Q5Tr{{UL28|b-jZS7@euB*-M zeO8yTQ_3WsP7h!{==Ck?N#_HR`mc}&C$2Cti~vAVag)~@hkkhNQ~7y6djO7u__2;p zZ*N}I;GB+g$v?${J-OSCfamoDQG0c7<@as*7iVUgweFgFUfXE4U+@|#YzMCcABzEu z0i60|^PZUEr77~~ZqwH|&PFf+`t$vHslp88H&8|a%H;4!?a$#)8Dc_?2SPALdvwoV zt}%|CXuIgYH2zoIl@yhmyIQLx+r7K3K1r+JUWyMZfN_ju;GPM`d}D%ragV@Lg0DFr zcfNWMdI8rT&lni#Q|v50X8C#%>JMJWwg(=ah@=Bx`9WiWoPtTo$2^?&Bc^_|)4lul zT?fl;ZKLY9es;T8PTN^%v`+292h0c?h7Uae=f9`r>4C_pww<8h5;!DacgGvKJbLH2 z%}S&m0`12=N#t;UpW($I9OH~~K5l!Fj2^wX&IWh`ii@_|y{)#IzxZ;LVzuSwy`H;Y zy{w+Pru^SqTDgn@2_cVCPI3Upet`RZdUKgnb{~+(Zh6Q&di2i}y?9W16V#lK&(P#@ zbM7)|*m0iZbm`7d7(U&9sHWA@cfGFGoBse`*HJEH-qv@~E|-1vZ%x{_mZEJxF(d`) zliMA^_53h;bu`99(6RJAi7m-K*csy(9W&V3;~3`$j`-t@XX-x_Ol8MR1N1BbYj zFi6i{$G0A%98!o}HyOt#8%fDNqxoZ}JkV5+zsT!@(E0#4!0nJd{Y@vNo87gyX6@=U zuhQLBwbIvXRdsi&y3_F($Ur3Eouq-&<^b&hxyDKAatB-;xH&6pb$x6XP(NiXU(dI( zpKy@_k1b8ZM6bvhaFNErjsuV~byGew!hbyCBI!(yW5p3Yoc9SjhkzIh~l=kj5f$sK2=co%P@@sD3O?!B~$^_ z1+x4KJ#{jv(2PEKw(BnS&=N&kzwYO@`>a=U;^XM&Y%ezYH zwR_95?$)~YT5Ee(3UHX@@(KR{YtWoyZa-XlaGM({2?4S|@7MGL^Zr$2BCdOKN%w3V z0#B*w@6w;;;C$R<(MtIIR;GBE#bMMrecb40-c-o-nqjnfM1YmXP`Bdzx2Ly65GmeKtK;UBN)KI$87id`*sG6n{E z{yf%xntJQ~dK9f|?%Q8?RGPMm%U$|yp$HpB26!0cXB~&-)7$w(%6P{ek8_@*8Q|m| zMg}p(S;HN`JAZVMk<^UvFb^62e&tMSj!q9^P7ZtY$5Gd}=|#5RRe#JKl6JGQX<4gl zbhLe~tMq+rR0zdM+8Mg2B<(zRJ-F@l{3S^6IRJJXX9V^<^v~4u>S|yYrx+Y?I$-xC z=dT}^Ow#t`k9Fe!6Z!F+=l=lLO{*(j?ew;`{L|@RR^Lxms=D7_CGOis-<8VVUP(Nh z^~bL#r#Q!;>ymzov1goQ=K~}RdjsE$pXe&U3K#}%K=sB)rZe=%*V8y_Ng9#JQRs2s zf=3x1r=b3&ucpm;bp2ms7PhwQeP4Sg)1tonkhQ-ocYL@Q80p)Nc*pt8Fvg<;1&#;@ zfq}+cUV8N%KgN?*w(jctdWMO& zbg$=sbzfU_PfsP&VTLRM2TbH1bI)G<`eP#_1Kz6Kz$S`V%(Ft$#AEwSzQvNL3*0$XT0LUc@?m{rcXI{7kInt$kVOr&5Hg2}!1<(@BQgESBWe0iQPMnLb>X{< zR@N<`@d};xx0*a6(icz$$R{^S`&vfa+u|re0aSoUK4qc&II_OEhFja+de6mHv;D7H zxU;vqu{V>g%UnE>-pYYib_^nE?A|!vZsp^X=He+%Ql}a)ackaFlZ%vY?9?2bq^6yl zP0BpFHhS24wBs7Gt2oUzpwuHJ8QD1}Q6&`N(Kx6{O3hgu{2ITBJb4wTg>`8ytf!7A z)wJjG=aS~t0vmR;*J6~!vnxe#-d~mFkut{H$Wo`;bYBiWfu((qO4MhD;gw~$o_NxA zxxVt%9$6tJKXefzju>K+AsQ(x&dzbAX{KCTN^dn+w7=Ci%LE#VTR|1z(!mDW((d9o z)u)y)6U>#17b}u$WnwG=Bms<&bJXY5;Eas={{UW^7;Z%6QS(i!DL-~fDd?JuwfEID zn$u-tmcAx4l2A$%?w>90r7LviUkYzUB-^##wzrM=gTX!}@tp8ByMJk>Siq(Sw6s^c z7X@T(*YLz-hwRUCggA;vxiGQ7cK{0Y4JS*3NYm`}`&n)$j?Nh1j%%k`E@V_tyQFkj z(f3u=ztYTPbH^As!1g)Eez_Pt zW4E}SA_JD^00W*dJMakUf`0cs$7-z7{G^PG8~`~Z9eF*u=sW%(MdkyapMrDu@tpCT z1IA8x_04MSqQ2MJf59=cOI4#*TBmNB_rKg}D@PtcVSq9Y2V7^Kop5*rN}Md_T9zysXl)6jRQ9_mITEEEi7SD@%~$;tdVKU~#dtU=xK z_Fp!031|ov0w*~g2!s-g6wi|xf#gEIL-h(U<@B2wQFmCzx7M{xiPuq zlEjj5bCO4(<8A>Q_aCKJV(&CkiDwHMxG*6BC1=P5@~lflPsjmWl?8zYtOSektT*{Tg#p)5RPJ$Zri)=$+;O>a5m?WVYO&c zl}t|0BJM-An7L8>AoVA<-sB8opqEi)P~{{=KYMyQmB=S+a5nMI4_xQ9P2(*cn*09% zI~8d~IcvR^?@v1~#l2UVIkrVsa}k)2-Uy=rG=~{bGl9D}BXx&F!KIX8SU4o+#Q$fdE4i zvj&!8aK2n%$-Ll#PAaycsC|)5)aW8UWN^gN$cWOs%p;C8&H#BCfKWzr_eKGzl7y2^ z&M~uTS?aY{U6tF{^ezshRnmOYi&4G#n!c+?7OtYwe64P~qo+yYLKH_5s3BEVQ~&?~ z1zv$v3;~RQ1z8snwm?Y72Rsf);QI1#bBud+&3MO)F8pVu&uq5K0$JTg%x>m_27=6f z?6GEz1j=DoQq44kIc%>AYV>;7h!W>YO&-O(N2N&(wYH(FsS!q(>{VvFw~z%-vLX=A zB%6`2;2qT--6tsW&e3W&L1)q%rctu0WlljixElqY^q96&w+{Re%5vnIyW2%~?KH@4DZ; zwNCmaue$Wo`@|-xwRpE{tsGw~Y3T2DqjybOR=eg_NanP=?HM$iO-oh3x3pVuRybf^ zEt=*vD=d2ll(Ws1Ke`1Malv-^ocT-qRJ_x5O;KgH^K1m(WtD~0s+V!2$Pg@3Dmtrd zW4$CvM&i3zW1n%ju+r}%iVK}LPP>LSW{N9|J9%S;`ZGkY84){oafa)Yir{=h@XJKi zP)DX(!K6<29(Cp6S+6dohzI?}ub$H-x;%v)$||#YU@HJld8VVrgsx0R`+un(5tb!@RQGmsm(u zWdwB@MX&^RqWPin5?`@HZ~@(NVhW@% zHRtwvPN4)kT&rz!aQ8%ABwuIq1VC8z|QAy?=x2l!J>@ZG)b zmalVTCao%3YI>Aqm15GZVz`CvE!IYD&dTB+HQ4^~#_IvN^%#uwd7s#F7_VqEfC}AkY(7a}+%?MIn)y}MMMb>MUO?xhBN)nu>7*?D)V&<;r z@covv9A@uJvq+}A3uS3F^xx?E7KdgeTRV7BM3c`uHO0iaiW3}-#IhlcOLsPw*LG1u zY_}%%>0u({P`E`?EUhe(=gEzvB|wlWs*>0MvaWD4Q^ctAL1U!GnuOQsG`csG<~uWQ zYa~f`H1mkq!xVmcc_U+)oVZ=MV^}^%iS;dCRW+3+6zPA&ij3m0vDB;-p`iSPTb8#_E(pk?5%4>Yv5Fb>bFv>r%5%=l|-7q_WsEUlnv=C-w!zk7e>Dwtjy zGu5P)H4K4Rs^x?_<)xK`Ha247=Jxi|3$0n@xRExk&c%&2ElHYAL2H+dNDdUnin+k9 z#>Yss($+bIYc8WDtT0{bSYdH`(ISZ(X?9C-E3cZ-#1JzKIbeC?JVoIBOI*B2;?$$H z((mpX<6fJ~KWu0%l~YX9EO6KmN9W(X#qzH5#_o^hMitHz<#Mx|mAPP>Y70y1{wFE4 z+p|eUwSAdNr5<>}N;G3nnbfUj{j8FbQE`HHjXHeF5R8i+i7LihT@H1Z?FjPD$loTRvWisjkiyZL{|~U6tuF00z!pOcUH0R--fjPK09~PEoHOQtq6r=i_N$Y?|B)S z)603C=6M{GwAxYDtIL-6L&U1_vuA7sJwdcx|Y~{%q zt0=ouPoY-r@wJ8&A5}eXYX^BztBP}s)@xa4~01oi%1aFUgz zoz|N7U2Wyj>C>_1%9DeXB_2s8n}T;~-)Sb>=Id^2?3!I6AOX08v=Dl5-N7UifW658 zaf87kpf|QkC1Z64)L@Q8v7L-~01e+Wu_1OYTOww{>@;^tQd*U584HDz_O#LHVVo6v#mX+a{PvnBcBD5LF#d^FGSYQ;m1SmSECHh}t)jrYY}9%7R93pCH>vpcM{A1(LgT0w*F&Aj~g+;73d;J!w;QF z&dxo0fN|V`k_HIls60sE5%T~+BaVQMF`haOzh38zXz9acb?-U9?@LYn5>~aXP zME&NU?$s!!+EIc}-A+9vcg^ozw%o3hQmG;>_MWg_TE`%}wo!3!AXy`F>Ng{XIc$@H z3W5%DJJwB>g#;2_tkK48uH?6s%P}_>4F>(ID_{t%ZSfzG2y&p7CvI|jFmv}nIOGx3 zdH@baagL|(p)OD++be*2g(ZX9<+oiL}?Rj%Fk+BRGB!oAeBxlQ6K3>*u zQsrQHqr8{RiK2_`Lj|D{$hOhj#;)QEMTcNwNHX0Ei9!^0clx)-zuLYd(&JqcdsuAd zicusJvWwkbeae2rZtb=^SmSun-+E5>Cu*pTRf~MEEcI9~?rpWZX(E+Jl`Xrb+nae2 z09YecB|{&VU{%}Yls|a09~&^gI!QZ9>z%8l_Oi3Gx_`>slWiuCtjVPaQs$qskF#y6 zDZgm#4H+NFnTWGpuNhYnRYEuzy0E`Skffh+- zl}x4IfLM+B>-Bg{|kF;%QPcZDWpSYnc%po!(;LI`79DPoL^~rlE5z zmazj2H;ry?9#~@%`F1{Vw2CPqjt7P%`%I!$8T&zz44Lv*JadYr2*ck_O-foc=IvyX zx?HifwbivZYg+!TDbEpFbyB4z6zS7yP@1C!E@{c#NxHQzo3n~gbm`r1`oIl6ysvTV6;pzEw$9 zJA_t@E3i-xIjp;FGF?JTtDDO^<pf=Y zSs-d2Ak(OZzmN(Jr zR$5k>ewvI^>at$N6c;*;?f#_+lHTlo|&~B4@>?Njvu)i)^_=f#cNsZUZ8n;EK3K)Z5Nz@1OAS0l z>8Wx>IL=V!adaszStSV6ij5z7Fq~RZX;gEJ=T-<^Ur^Df*XF#?BDm7+WZQFV6w@rT z#c~sLR`TKru2`Td z-)D+uLhHByS2?=9wvnUUS;K37y3NZ$FWYS*fvt|2bf;mD&n-B*MJI_wR>klRz)u?= zX4f>W3GZTuQ@4Fa`U^-d7^F7M42oKGSV4CMpX|mNi$?6JI4XFo)Lf-e$vqsUB}?qP zCGOjrD|=e{E2iC;pSv1dtuAF6aF!y^+Q;6~cX69u>z=7Ltkt6{sya`Hbq!Zkw9#!X zE}Hh?%u+;QlXbib?dMzwaod39YQWI%P$@`*ULII49w(^mv(F zroOn`Ee-UIzB4OKi}HXv{f{T^sq;#85^|DOQHG0^y&QVES*~j&tdmD1F)FHfitZHY zQJaJzHs3vHDM{3(rDZo27{;6>8AVERmE|inx8QFAT3p->YWf&82rc}mqL)z)ENo?G z1x2NRM}tthk+4x2KvXzcCuJt$4RuP)%WhkgF0 zA8oy*tP>KETE!&ni54VC*J)(&Z;X5`;OHUKH0Nu}oj=MD*g)veY4XaFhMq>knXb%X z5uQLqWwI5CUB5i*{wdUNb$e}EWihk?C9$!*-82FwC5*GGG%q)t`<$KX8CWksGpy%A zggu;jXE?aZN-LR0TCaP3V`s}5Nw*}fl2%w@=wmVU-Dx>dr7Cq{P1I>O2`4UES8?Qw z-IV7TD5%NWPEAT*LU@znmW8H$nO^F9``2j%i>Iz^E%u{5y}>hiLhEy?Aca(bu4Kt6 zwz71Oi?QF?-hHQ0T{7TF9M%bTlg)1+gh*N|i>M-%;Aa?USIaTvI2>BZxSpZJ7fs$hR}d#Y5^xa90A2@+Gw-fS|72r7b|qj3&PW?O9)q7%`9w+ z0g+k6YL44NF(i_p^L=)_=RQU5rqYe9_Uf*?tJ~7sqq$`GIuxVr9FhCMo4NUo=v-_2WZK4*8ikTlUm#pJm&Glh_7=q6lZ}W^Bp@K zL*d*ygnk~9%Tu(EN3gKA8n&HrFpZt9P|4H7aFo^QL7lna)c3*B`sD8`%Rx{Rbl z;hzBAc#78d#2Tgjrj?`HNaRU-aEW(!Dl@UWFZ`8Z%tOVr|gH6N#mL#%QBbcCafflfEQoXJ$Z8Il4rb`kwe6<~v9W$n!~d z`!w5Bn1Zdh4ErJpu>jueNEt#)R?2D+TFE)ku3)zoHWR>Z?subV*Rd-+_pwKoXkw7C zg3@>Y=N}k^C&h_J1CXBa{Aq!&j80L-D zlq(^H71Ms^5*0(wL8@v00ARX95xGUlmcPGVPgdG)0(_*4jEzrg$GNvw{ z;J*@IUCV0@n|m$QzFzJ&jK}4c<#)5T&>zZi8CGK3NZP$k+I+B$I6g;vM$UF}Yne9V zc{ODBZELQqg*q~wdDpEN)lLdhjGZLaG}I>;^R)!|rFlll%atVD6pngFy0{3pAfkf) zO}fT>m}4?Kl|%z449o*yOS8xvGm#M+0*KT!q$oL53CRF-JbJc^ z@Vi{pq>61?RMIV3)HG~7%|O67VH82UxLK589hz0o&QqPW?z&!yp=k@VPtxuD*4e&$ zlv|6b3XUXs9Xznaa^75MGtgqTrG%+Bc{ffyYjFWVT4=#OAnqR*Y0@NnKhE zdnNF@I+9XTZM~`U%IV$NpELM(z&$iOp6A%++ifM%G4k)2eNgc}PHw{rEa+IU)2?IxV0 ztnV$8SK2E@<-7Add`4x7uICraN}StGQ%dbU?^0Hs`}{GwwXE#ziK4TCVYP$HiB!iN zR_GQbBxHaTY(s!XK|J&IgvoIE{us!~X5b7QFlNbL&AmnmG`90gGORZ8M|Tq`l4iG3 ziltPT;)`&7!dKhAPctZ_kgP^4htjkk5#DOocYZ076pkW`r^6qgYiuDB$if*FE@T%f z#75G&5jio(w4&|}vz57dV&6BVqL+T&NqQVgoT_tkRE%6=np(L|PWDl~@4Is5c2Rd~ zSJ%CU7GT?$$(H$BAOa9B0AsawjCI|}&(@#h6wk^4$4nOIuK{zD#yjMn#-Wq#^2_DH zcVb4+r6aVL2uR5R&B-5lkQZ)B;1|wKJ#6lZ6}Y;%xs%Fe49y+2r<)I=+RpS6|Rh6;WqZMP0 z4@?i|0#9tt>XXMaf_Effyod%kkr7yNgU`1?R_*K--V&(rq>qft98By8&Qu$Tt`E(e z78^$y$2DdyYgPT-|n@aUc!8~TFJ?zq|%O- z>e6jrTkO9381mgq8kUa2?%=7wRcloa0Ageg_W@LKf~5JUI9S;6RpP$9y7GLT9{Cbo z*^=T&A&wxYX)*&bkSWOuSvMRLjBO{R3IeK-f;C(P0I>wG@eFkxve_r6Y*>!uC_Y?Z z@q*J0!2M$$haJXq)aQiLZv4*Ol3$&#=kqB#ZAmz5eJ9N?I=#e9 z+H_iM(<6jf<+-|8K5iN0oLV$wE^`-7OX0cXqm1+BM}$GmS5IoqP7x$|)zxo!pdU^>Ixn zcg@VKmjk1C4^6R%9YW#m0CMAz-hr{UChV;J;r`+wY2RxI+*n96=>8( zF$j@}3Kt(Tt_T4DH>59`J;GR4rGcj=LV*n)ZIzI%I9 zP>fZQT6g}m`4Z~YsM~K{+O@l_Zj#kn_Pf)448({lDNAw;XcZqQs-O+3p#vTV00ZyW zw6_r@%u5Z`wXMKMSrpvHCSdp~3KkeZ0bzjHCmk_YjCuKY5^>9M-?lNwKy%3y<%s z1QDpuB;h_>=dUN|Flx%71QMqMgOW%mw;sR!da;5DKPVjF0fIgK&wg>#ih7LqAP`SI zk0(9&J!zzt%HB&w_bV^Jhs`%>%I{uXZqizBZ+SPP^7Je1oQ7LC=#boR9$=?#4eX6P|k?Uj5v65y>E92N)Uk1AsZ>BfqzG8;?Z*94=3&$>=ln zIL2t(`p|c~e-lk6le1kv3;FGF53$E1+v-0bZoNHexoyMd>yUHDetkD`I)T^gQf(M2 zPH=E?alyt2U#PPdiLwa6lI&Hag6on1G)DY z=hmlgmR?%@`wrSJyV>EMyB_c0!~hIjzIO`1H(xGXQp@{bR3T7o`1)l##_6x>t}yI@*7=RTWq)4 zU8L5YuG)7Rp+{ml40`nIj+p1ZPk%}?RAdr( z2Rnhs1F^u##yf%6y*qHp2b^<{t`8g%agTn!w5MsoJwYUnanm66>T~`W>PDLR$!+8{ z-d9>_t*ZLKvAAZJPxO@9FdZG;A01=BAP}{K_KVl2LyA$=uQp?Vb8T0BO}{9 z1IW)Ku0Kys#*$LXK2;3de4y>?*BobogV(9+>g>~U>1U_i(4}UTufDHj{{S8BYhUHi zVK{xJH^E)Sz{;;5cNxy_Pm~OI6h|u*J!4jEFTOF8&I#kM0OXpJb7UOgo}i3^HjXpf zr#`174@$9HM;l2h?`D;YHs&N`bl91~o_WV#N`%{be7i5s!S31XtI=Ca_t7t3_$aZs z^xVuC9{4%_gV274qrt#E&PG|d7~tgcGr_^nrAQR+!5BPt9Gf=4GHf%}z1{70^lSOG*RSQ$?meU*m!1h7G0R7{&nTJx_9QdU|>RifIIr4loZvpHu7W$f=6G*H6d2klVH0wb?tZANf73_S}rF z23QPZI3#2qojDwLKA7vAQdTl_#u~x^BF?uH$cY(b-?8 zmysA7dZ@-uPY098`g7~YG^8jaYPVmMoB%rv;~)%hd-Ly7W3k2$T=eO|`ub--N-%IZ z#(H4nb>I$%@I7g3&*ayAHWS*H!@OZgc7h{=F+U(r@~e4kfl)t(5Va`S09^B)OfM*Aw?@+YPGqn^GpS*B=j{}~25DD$>J9Jj>t-(8K zzUgnS{av+db*}bc;#N=q%AA4*0pl3SBn%PgNzQ$ZDy*AAw5J%rP(W2v_kiqs^*PT> z_eORplf!Q5*+Bpv2zfp zQp=2FZsP|W^OhMO-N@%3d(x|@8-^I89CbWnk>8=lI`Pk5l`e8uaTwZipdPsZocj)g z-0{%VO|%9;M(zmibI(5c1ONx2C%rZL2b$6C+5Z5;cNE9Cur0vI`G_Q*hmc6%`{x{r zYQ~@e!3&MW@)RDJ<2)SWj=e~ub`*?fE6LA7dgS|_NF$D!??X5$2g)0^?BM5&j5kr7 z^S~n?N3yo}vQ~O0(%ybTv)$iB-j}w!{{Ua`2efgpT=Zs_zT=n|)rx@d4K_IalfJ%&!k(}fYM)f(y zDRSEG?_Ik7TYdike&&jHNjR-+udUa6C)aC#NUeYroaCs>5EKBQ=O-n0f!{bDykyrs zABp@qajCYCZK_*c>d1`7$_XB6Fpc}g4H`Tf&=qD=Fvj3Ik}G=R$~(wrw2-j3opv~m zPcBzR`^Y2!l@10OfCm{>Adtg8%ftE}mdb3j`ztn$Syosf2H};D%wFNk%*@0c$9OG) zlh9PPQ<*5JC2O}Uw)~=&m-CbIO8S)x;87j zdW@rEa8?<^0CwewIT;woIL{cWx3|#SMsV4vs2qSYm zU*a84!*J%Il4a>at|y45$^x z>Kg6Vou#UHOHR~v%dvj;Z595Per~MQ-Tc;>ui&?V?ZGP6@>unk$?6HM=j~p=38MbnxyWMB;s;jGZfLqY#ov( zMF;HY2mz1Hn$=RW6;*U*+!PfXN!{|OP4a&TVij*Uh(QCIBg+UYj=k<94&T-rX2G+8fA{e)3V z7+cF&fLnJN0_JCwhDhHo3zfjao-4y_Z}cwRXmT1~1;8|d(9?o$5p7EiRT&ZQmdO34_K z6)`2WLNd(7rpXJ&>7NX>i-)+ohf}n)f=ipPu|W2*>X1F0uKq@55*dj(HIc#X~s&5Hs(N4ml&>T{h&{ys#~y)1_OBIJD%7+B4o4Z?TP#UG1 zYBw5JoLf+|iYcyONTq1vNpU23xkPJ2CKwll&LmTnWfggy@G!uU-A`{{LOoljVVbLD zq}x~qg4GOb=9k*e(oZ8Yg)cPHWv(5^bG1R?QE{4~eXi(QLzphLOB+W;W-v`~eB3VG z!3G;Ra=$L%JAy#w)3&u7SN*(_j=kj4etq7{Lnj2~YD%MRTFMQ(tGPAH7c`xs`ETy0 ztCp*)0rLSC0&k+FU6yMpifxKu|X| zUkvNMG4Wmfr0w=C7RGB+E$hTgTVsMdm@MtL0Mp2#Z{Dy1C6%9hf(RYohdc>or)oDB zw`M8Q7lm}oSeiw&bhkj!-CbKU2%h2@Q5p+?UF0gVFhWX<94l3;A9wdOnv7KR))!Kn z>ebRottER!C9CUIu()hBM5=$b;vwy8N|WE(N;0QLH@_s3lbcR&mBrMk<;@hj{Sr8u z!V8G(Ah0tc#v-)0OI7}!cpUC>Imyno(zT`5UTH6(het^zm2~S^ zRVTZ-W4bwSE;g5V(Mqg=T}+6p8x}-GUZjk02+v%c6Y0h?jzAgUVxy5H&Qe4S8F##y zDyxs3a58hZ7$ZEBoO7P_1k_V++|^mzZ4%PjbhnnbJZCn!xmx#=Q|9HU(r^iO=JfgPd+TRyh*ae!p%r&0cAQ+L&1*?D%VixOHITg}wx$Mj;Tg`X8(iMvYEICVpFi13DoOIU8Cp@@s~s$sSC-e-aOqLc zac^lX@l3>smL|GnnWI*0L_+ytkCr^}1`8E_d$cpBph)qIA}T6^zyJp3 z+|1c+#1Lt*M+`-s7cT1ky`9Q)P4qZu7|Ja9%w9B>F2!6&ag z=Zf7!m%o0Rd0BkA9Cd2*-pMN^cV^uF*7w`&#io|r$-AdgUFcQJWrCM8J2IqkA|puh z$XJEI3(3YY$p8!ttNl*WC$zT#?j^sSVv0LLOp@@e=|n=nRb^@#d0t>Bb)=5K8pw2UgJ+>v%On&S1p+&k_BSP6i5cd z4&UoHGGqi}ovV^^mWegGz182#&f6!ppbKckYWgA{8^7FTSFMHW7nrU4%HQWzt zBF$%J@-P9eBr=tb7_xlSjoG=HOcpE~a{|A@6bTYJA^TnR$D0MHh+Mt1OPM28Pqf?_ z4sxOpu8fJd<;lh?R@kzj^G;pTJ?IJ8j1fbH9=rDjY;)9P5t#0yONhSBG8>5H`K8~? zOalf~VUkEL6}A9(0fT}_s<)a~>7|#Rn)X_Yol5E2$td4uD`tMU|F#V;KyH!)$E*3ra>w-Jh3k(bldqw7D7I+A#u3w;=ISi{w)^sK?TjR zgGn;9@LrVl?MQ>>htb6AYhItsX#D#pdRoq`SHEJlu>X&^RN$qy}Tfdq{lqkxj zRUStrX3|d5X-4*nZMNRrwryHY-s@|vwbkwIqSRxaNTZ6xTs)Ga`HO5+8KeyCT}!BS z9$KBqMh*xyj z;htlBOft!)3s$$1*G^de(e{h|#76QsRg3KQ&vPP6B8gQ1V!mx$RQ9J7+D*wj-CtFv zk7avm-m1%|(BU%59I4`JIP*|OG$ez_N9M+;VnB? zwVOe=u$_jlVQqP79n{}wf>gG*j_T%RlG+>j#In2=(fM-uQBNdD6(u##cy8-V(Di9` zzZ5mDv90R2#qHuIYw2_ucL)1SmYd{Rp<>~oF~&@A1W3w+81XyJaNSLAsYi)l9&l5O5R&1*X=B=vFkt!v+>G3czer6^9F+*H)xBv&m@W~X@5 z_KmjJDve2UCG8wkUHP03aq;$*WUqaBrQKcYTFh2(%^A7B5^1)P86%c>Y-~$@_WJDu z7#)?&5i=DDitz0QAGYez4MHoeMhGM~cd$jiTkELfDI(fNPUa=$jYBc%ZxzCV05#s+ z-fQ~CrZjP=>AJJVXSg0Ew}$9R<=e*bC;Gc)yoS!w43xGu;ZY;nrHBh%1H1uX z4S;)TB07z(oi&B_qpeFIi_Mv*jsbOLQWy^aRP^&y99Z{Qv-9)1q!M8ebv*k|FjQM40IKt4JUo(=ES2*t#c+UR- zUekrF&_knHOF0($b)<0G*xSJ!#E6nfYZ4@LFhvnbB#O@O8%!H}mu@k1STDRo9+#zR z0`gmiiXngGJ+x4-A82)r)k$>P(ZZ|?OvEaNc2aF?RX1B zk{IVIJk^EN!t%6J0)VWj>Njo4)6(za(;>RMHnOIqmmzH$;@1Y+E&l*9F-&8fBxC-q zj6nH?WNoSmu6ZX?rR!^HB_`jzlzFcNm$;m-WYz6!#qQU2B(V5vVWQHU6sg7*aFpt} za#WM3{jBWOl1AqMX1vox*Df@>$)&!AEl9_d7ZXJl%Z7(CM5b0o^R3!fc9mr;l9oHe7CFki z)UK{%xVe+e2I5~fcw89}O6p=(CANl=H7(_kPQfGNp(B3NM7+F)&K*9|d$xNwX=1gF zW|}h==6Phn8C47!vyYdcAXbv8DwAB7N;*aqb8%b8iWteu=%ZOOCWd@Z5)PsQFAwUB6V{{U*kBpQXzsc#vGUEW&U#dji1 z&}LYHmi-0Bh`l6l3j8`8~gL5-Sp zh_bdKSpfv_{t?i%Zx-I(T$QUMN;q*;vH%47yvjK_f>zOEsid zetcmbRY+dYf?|>wSfipVmr$XKuG5EB4wC0eQ+&F$epHlRwJ#>xjnttPtCDW&$t8rX z3{2e_&YdcL)i}a#KGC^UO~($soFJuA5m2i+Hlqfqr4-!f=duVcgWO))+$GfVwc^Oq zJc%yg0>HGh@fB& zm7{PVd6^@bwg_Vz91ZZX=0pcMY_L|q`FPH94MLDB?%G;Rjr)LI`+6OtaX)wveSj)? z73Q?>WYwPUO_Xk>~-9Osmglr}mXjP}sdVTR)J z-5*b%QHn6YtVuMe+lEA8Rx=o2;2g;!DGb>o0;xhaX+>UKx06ls*`;{JJ?yXLZnrV1 zI*Mwf<<4sC8moy~(`Ad~)E2}9+>7{hy+28nMQ1K>@pkHeV1>83A+hakznmF!+ zGquFaDDuXh4a%4A`AZ5VdjbczqMqm^uV8?2JI(-Mim%b#|?ljA1x0}nH zO{i+NixntCg9X|hjby16^OZL7M@zG+S|y%&0}4i8-;EgF+)+D+)xVv<(8 zVs0(4xfD5 zeb$w$w6ZWFTWe>!iggDIA(klE5T(crSdo?);{!_DL9~WRrQIQ#=H|!7t^CYTc~= z06qNOu6S>jT+*LCS-Z5{oE_ee;JjK^R@ri;?j-cgOMBap7T&?PNW3)D#T#Udjq$Np z?gIihU;*Bk_L{A{uCnRs&_xSPB=(DOa#n9OQ7zeGW(DL{-Zu1AAYhv6e$s8!M+uF7 zQZW{CNH`&m0+4#=C#W3(s-|#QZjp&%1D=GpBc4gfYz*VBPC(|ZsY_=5U(&HL_DfrH zOS4IG$?K-CYjWtCy^dh%y3V4zw#jl0C6X0md=& zcH;yBJND_0{qsweZ+85y_5D6Vl;tI&icQ@&9n)=DO8nf-M%@7MVbdB!;&wCtbt`F8XF0D*Ejo90%M>aD9%OG|Ch zcYSmsU68KCML;?E0A8e$dSsE@oUjA00|bCG0od@w94|r!K>0xDi~)nwwN2zRu~_pX z9;kzs&NwZ={XprQ3ek&8l#pcE5F0}?FlIPjKnu9!5spah>B;?nNS;?Kr=m?>`{{e7 zX4RTnz4ljYSCFXLB}UaC<dl2G9Py9_K2Ukd?~~W-NA>-Gk#S1`@M&iQ(xaqqjXZzSSGlpJt#_~#tZV;z9ca(_ z++*wO`WgpoJv6tx?YsLe+osxT?|sUiSjh*m03Mm^z&%DW_Nh) z(t$=PD?J{oWz}tcZMFL8yImq^!BR-%4u_!UgZ#d{W8DIQo^m(?k++gQhXf_su` zU8f-K&rE_j^**B+&OJDwDu55mk;y&J2P7PJBz4CJuVQ~lyDQx`noCyieb>)xJL!Gx z)-k|r1|t9fa(O%x+~b4o_fI&ckVXLGIK}`yK*s~OTpacMK%5L`jDL5I$KR8Tj{gAQ z0`)l@^#pOq#(z$~n5H#tmEU_U^>=$;=i6thy-^yHFf-11B;@nh@CSU3ze;%+BkyuO z2>HEpjzHiLc>OBCTpS*R4^7=VFdQCm0Q96Fb?KfmI`Pgk`ucPAq$S$iueP_-T`z8y zUaz?TMj-dW{0Q|OF^qcg*V3da4@ST}M^VSGxB2gilb=kJo;vf${5^^K^r-X6;NvA! z007TJka5?xc;wQHz5R6b3oVjwTW_;h>(fT>-pjazbF|>~Ju%R6k~r`6rA~5j#yM@+ z$j(kZPI%8=J-J2ze7NbzBcHB*x#0KD9Su1~Kx~BDk?WsxjNqOJIPK7bg+0E1qXnb< zv|9CRt?ahi>iUE2+tV011C}`_zbEq^ne9(if5M{IM~g=Wb(0OWyz z)bYns04hFWNdt`JkTb_z_=8fLSZxnO(k8jMgs1j~se3GTdR3A(8)g~W_UdL)@{4;( zV;LEdK^2>nV{L5PNh>zneG*-_ciVl9BNf3L=i7U4DUAq7qEsk;B zLE{}y8OZ!cOk$c#76CHMP6$#C4l;AbdS@q(UX=FR8U~%wRB+796$_rFS<2)dpb!}P zWa6k@>GR%8Y##NktYXZU7S_wMTiF!mBzv5L6|xW=<50$DMOIJ?5q!@}Ep}`A{JWCl z+qT*}-qzDc-Fj*zrR+EUd)qN&wwdkaa*U(RKnn#ek2OZ%H?IKXcH=`Hs#x)ijE?;M zG1Kw(6(HD(st3xTC<7dO6Ufg1p1I?bjwHw&;E+2U0(d0!Bz64h#kP`dH?8fbU9A5A z%vM*E_pN7S)%H(Iw6$$Fs+kidr6p`vVQc>^R4anIrHRNa$nTQ5?#*K6L-X1gWmp8o*m zLU_sQI^=P{AF2NUKUGG-1aqF5920^tPZ-Z9w{DTY0@z*4nW!qX&jO`fcNkZaL|b z+*3mwV<3QV+!6uz>PKEMef`YmkTLT5=LF~243Eb@twsB^WV7apI*+`+po6+x#obxlb#2s2mEvR0uFkLmb7VIuD)Jtz5PdhQ|h$a((S9as_vM%Ob(bM zsm~*yyY5bL&V4h*Mpq@lh$2{-{bBy{Z028~Bf_vw- z4>;@jj{WJyB(%THSWn(*TH5ORH{EEK)&*P;Fb6zmxdR_AdjLj#I6deY7*fP=P6uP2 zhaGt5@%$-E<0l8u5;z3ojOV{!=h~QCED1Tmc6UU+S z;;E~vcPpls)oG$@O?vNf0|Ut2f=*6wJ%`W`NayLAVRji%#N?a;J06^#NbBlWoygss z<2+;21EJ@zJZBi{X*Uks`}Y~+f^m{LE$VW5b5VIK_57W`q$OmMZq2o$>2}jeb<@9{ zyN&sX#z5yd9nWFwj^~eVyq2*z7$jq=@Nzz!^VE)U$>Y)O!5|C}0LbV@I6sbg8O~22 zQ%ULc$6OLmOapi}|@A1DyZr)+pdf$6m{(Wwh`~Aam3BczhgURd$c=gBl z=8z4)DI@`may#?{j(=QwwRc^xl+<~5%x2?IXk9246-Xq#zoU}^KtG~TlTdzw1AQCtj z!32zF9RWNO?t1fzLVy9BZUh$KfI%aJjAxQPeL1EwoRP=_fzv$X$A?UH+E z*Vdtvb_oY-F5!jA9Or^MU<23r9Cj$ei>4S{- z&wiNAFEZ1*)vK-5tFfvcd0Kpg|1&BR&XQ>CA9+;;p@NfVe;I296 z9SG!uoOkWthC7fCQVGsD;EeIfUNgw+oNxiasF~X&k+2m26UG4K=a4!3zz#?RiYFDx4$c#IK@=XPo*b#(xQA21*&>N&!Z zoQ#|{a1R`DoZ?<#P>_{F_RGr^DcRD(wFUUg` zBxj=u8>1|W3bzdz+w*5R3`qlTO#1q9Q_an0oz}K~y6>gc%{dfw*6VbwbnRxEdo=E! zov&?7yDd{q)T3$i`^c|gjf$DA>RN5|7Tyy6*wt>d%{F^W5gK`jv0YmJ{pLw7 zgoN#v%oz-=iuCAp&kask#jWYH2$yuhE@K{2jDTd`$$-Q*(z~;dmm`|<-ye8~M%1(! zEHuldy0*HwF`p%{JO7EcM-MPPp+D zt0dP6rulPOX_0}pKeXLjXJx!nIxLqG%ed#4+E^A#r)pL<`j3mX4-;H#9vhbzQ)%Sc zUTG3rxQ#|GF5;QQX(BenNrYs$+BdUj#ylZsqiPp=q;YDtNezv)#I}c1i^-Ntz@?(L zl42cT5-#@L6H6PiEO{>?gTJGA*F^Bm+_u;D_o;EHL}R_MlTnWINMsC(#so5XFo{uw zhj!OxP`gP79I(VG#xktnqj$+KX)7r$FD9L;H`XmA?%GS1$6WC46O<`Nw4{>ukoIxr z<&#p9jCmyKa>w3NT+&)MtgdwL@ms>>&7|6Pu?wQ3!vTQXDT$#+hs%sagg{~{P<_&* z00WW_={ow%bkfktXk!wj(QRcCa~To^0kQ`hNh6H+uMqfw<1Y^8Ejz+i+9lwS zbP$=NOhS}HFL7UwFSi zpZELydcB^{$8&OZ@rWavb{`1V8Ic*m6aupzJ@vXUeq*RtlV4HcccArieY59!22~O^ zUTtuAX-;rS?6zI_w1&b$`)QNQ3w8+&fkkOLVZ6R1zQ~{?CQP{uuQc{!XtM` z;f|(gn(aLQ%R7g!`ST1y=5ueal+IOFuQHobwKPTfcRh zX>mzyBs!3r1-4oc<7sIlH+Lm{9TqrVX41HPB1Fo?oXfo%>Jp;j_Etv|%#c2WgFz_Z zqs1*~(~&F`kOV!4%0{DDtM;CZg>T~DWSw!#?Yz(#0%CNbnx{1zbF#g*J>+d*KC#He)AUz4L#C8( zpxKDdavGLd(I02iU3hV)J%i*ZyDOZ4*)dGq`zrCc{HxEzkAaHns$_*r2HeRtZXSQB zqB>HSMx}DCp{A7Js0(XE&Nmm$(HXb|nr80+1m;hGkQCQ&vb#3FVZU-(lw(~|7NobN zEqO3{Q{LgVpsJyd!)k?Kh}Z)i4Lfnxg3EA3fh5{%h+00{4$ea=wc0jyj{aJ*C|dtw zc^GV=Yci4a+B66=W4Vfy2n_TfG#O>fJ>oQjgZA%nIA46AK3p;S@>}?~&iXGhSE3Ka zq_R?sx?*ToVzq-p{&D2px}JLKZT3j!)|8NsY#on(44Kn~516W@&6D)5s(W^ExXN%L zXzrP9V(qcmKOI~_t&NwZftr~fW>K=K`K{;;`^;PQYLn&YH2sgrVn*W>zp%Lp-{sDR z*Tbr=v`kq)Yi16>^;qNH?~(Z${W|cCNYoc$=lbrpde2%!!=21pR51Ui9J8zC4bpw4 zZ3@KT5B=+1LDC$z&t22&6B%f*tL|(oU1;YPYvY@8z4%dGvQ#^xZoHQ;j7FeJi{$}1mbG6-C+x}eZ zC=1EcQ5mTkfU4dT8xA>kb0tnoUpmVBPICxv`thWzYqzw-yE3ite4t@nGmFQ!SW$ao zf!Z;PMoGzQ`Ap7X0gmOG4tUMNk6CJ4Vy^qMvg-9jsI`)h3?t@n{1yue_44A6j8*R5 zW(uF;_Kc(8WaBH5480Z=tIR!q(;sbTl_Q)z^QxD@sUUPsYR4c4@chTDJ9z{|Gj?o- z_X+KvbN_?5i{WbVFWw6KVjb`Hy5W>AA=52&MPlv8&~x35eh$u^>*{$DIvZzZAzc+E zfnAUx1%lN3Yop+b?>XBWI=0>6Qy8PH_I~}H>?*sO--85X};BtfgnrW(9$)VOYQ-?kD_Lx+Y}nHc!=< zjz7KsFm$@6#@YL2*7xflTUdu5OE+rr6!ClX5#b6!nRXG(476;!lU`3&PFW-9qR`^2K*0`(#vP>hVzT%{s#!Z z(ckJEt8MS4U;5#WWheD!V;jLCgo>1|K(F`bM^4`$H~Pm1L=G)(W#ed}$c3kq3j&XU zg^Qj#{CtRXUWl%w)f&X%howjbz@2~FD~u#57{6K^DB8}@9tcq4Qf5BZVIg7Uzd6m= zJ#RZN)}3<$+D6CfiEy={bYh zCHiFg+0a5&0DcHTFnF-vMx-thye;$FYj1eEbkVCoDceTnzDz zofL0u$G@-*R_@mmO@H%X{S_E~i9uxOLn*=SiDjnXhn|d-4^(xcgIA-0V|6Hvra;b- zY|2{f_M$d^H(O{zHg>&wWJlT{rq{K7thcKsT$Qgs%a#+(bF+3$f8g%@*da4~5^~Jl z@c1LMyQdJJ-I+(&Yir!(VHB)1Rj;Wfp*j)!Ra1TlV{q$J2O8w-{Grulm0SY}CEV$7 zK>3$@MA)mioi$#vwf~cXdgIpE9Jj%eP+gw8$lK}~fOLDM&pUUWIYx0tJE)5<|4W26 zE~{eR+DmI=%#)mldg#lmU6X+ z!TZ^h3Z;4-lgJz1(9$rlwgo^3?4KjnT79qAR%`)R6z;o{>)!S}+Ym8nfU>5fJ}?%4 zVLT4Bz$P`a9dw)6$#$?5ZVwqMm+iB&NpG! zH=S=G@fD(zU;jGOsgS}poK>MMB`#!1Vuqt05O7|+cQ>TNKRDXr%N9F_qViP3;%x1E z3|`#lIyVr&^kD5l=tHUatJibhC(dc^ez7Tz5Tm@jQ_6dk9g+2Sm?zF&oilBqY=9rL zb_;xy{~^KH$JP1$Re){B_riY@AM*{H!YTFcNcBZ>Tyy6_a)pS*UVRTL3{C3;h(FQ}=COzBmCrcnUCDKqc+sl`C zlOc-%@$p&H#Vh$45kvUXmI%iQeF^a=`>NuO-m^MhwGEl>5njcZq_{@s)hio1><(Y` zYr7>7>;bc1gTnToacw9QUtZ3vYigUWz0v$BxjJvn*`=l4F7!h26}Uy>FR z|B|}Q_rG38wpR}Gq#MrhZ!7c}k2m%>u_0H5H0e1fedwCUZW+UwY_S&pM{8S!cfL(*_mqyrq4}`^cNW4v?M7p1~c4lEywI!KOZj+P$Uo3pqCukdTVT{1>f!jhV&M zwd7=9>5+}}ue|$`F*>6+5KBrcW~uqUBO`jo+zc_+1@9G(8|mFZkC3Bm%ZT?~9h0Ow z_;ztKxAeh&#-RE*cM`PJE<>_^!(Hl%WXwY&#mO+#gI%|*%sL{x*x^gi1LF;YE68A2 z@l%^+Ww{r$)u>?*O~Vv^g9ELPk@B|x))*Di`-@jf@V-UrV2zerdLFI#m3sQX}mb#>!`76N%Y#&qojRcf8m4tKd+`vv4LN zY^7SI)=5$|Hmb#o)wH5D_N$J+Z@!D%B3$LzM1pa8v_jldZIF?azTPY49hrB}&vg_b zzoLSlFT99rOoq8nlRiC(b#67VxWi~4{+a>@(=!KdyBGsy`{PG4#@sW==N{(#bR&Xg zXE!e$TPd3vhD#3fe2Rl2ORdRq+?BcM3pdbmA2q%faeR<%3f>)?GmB%H-YI*PEoBFn zZv0F|f|W|0!4~&jr;8M3{7x7DZ6P8VxB@&L5oXtlU6$OnOzkX;2wv2Wf_T!)D%D%(u^WahARP)A!mXv84PrBCoj7;g3zHMxgy`>P}xSy>oIs$>rZD12H>8z|nlm zG*oof4RFGxE2%5%aKHi3CUC>S5f`KL~FdZ?%a@yA`kNrNw6>< zJ_e`zvlmB~3<3@vfxFeO%zO)p+`<4;kxI?r)Tj2^!!S3?(^NQb&HkG>)`Du9zu+RFAgqz(&q|AR5k>F=q z6NRw@ImzxI+zSZLhXmdUbkrrsh;|3Mq)%7j!*pAxentj-F~E0t3ts6Ry>W<;s3#ED zIC!sLku=iWbK=rtTICaZACW=LE1!abbBq1L_`wXl6h83duz~x%q-q-jm)Oo|pT2{B z6j!e3e}LM>Qlcwu?UYbov`eRW$JL^^Z*od<$Eid(eA!5 z4f5VRDUC~(pcb3{m1%mx)4MBqeQWY?wrgm;*u_~1E2BFCI8Nc>AYpT;0yAQ+m&ay=?4{bb=Xr8v@;W-me=;Q%QsEh&^xH@?=k2 zCX*#k(VQ3vDSa$_opZz*OQuxd2Yfs6gGXvYJxS;~XZV;7>jx5O`799oJ4x|hckMTS zBli#WOKuIFHEo-7-qe5x?0gJ7CJciBt{)qE3k7}qM_)zT>VUYnnuCsf!2_ddD4$-n zpiyy?Gz|b(nHL3o3B^?qONlq3_zuU+ zY|5GK%DJ5Ez{xRk| z_iF(SL?E*d+o@kJmt+K8aWft*`Cde*}>v@>>=KV6(3`GL4`fQq29K$!$- zDuMW3ek!gzwf4#?&_%>4V;m6N`5Vc<6gki=ucmm_fDqvAQ^ zK(rGBe!wNB55q>{?}sHb`Yw9v+dVQ0)jss0bBa_dt1ltz<%(V1SC=VJwTy95&?#qh z=2`bGGKPzU4jc#gr^m*QMZYL9{ODdW|1Kaf9*50{PthfzT^O+!!=2g2JGb*1bS17xrz}TL{yB??G>m!nXvBpAi#3-7?M3%0D2=1mRy-G3#FV)BQ(T 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

7E*Y5Qh` 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≺z!#dK|H+*w)#XPr6*-7K%Xdp(pP$ zBFF&%Fu||ba$gd%OxZ%7GT0nTv|5+$*E3xv-y`p7rK7(#x_&vG_+i93Cp}EPyweF5 z-!v~;N-FYqrrW61BrPMV zk@x)A*j_|=IWgTTj9?%fS1Wh$zr$LS{ing&*|C+7lcj1*E-g{;PRQrXQ(Eq9Z8tJq zU9ue9c?E6!jwaG{WJHlfYrJ`DGM5NONoePcl6L}j??4wB$>a{2)_Ee5 zH{`BED>LkyW^zK@pmmdR1O<{L>x_;KKSTIy@jFt~7e>;2AFArNM1r&FHqU>iyk)Vv zdz={JQH~s7jm`4lWc`8Q-`I!Z4fVC2wc|}*!@+uW!B6xnQo63AAOkMI%);8(g&|lq zqpC9Jl1_eaG|aGA9(dy`(W4}vxj830rKj%Ga@R+GRJz{Up8f*^h{UMN4Ni4p+-*`n z15Qg-QQ8mhZ(AjO50?${nUU5>A{g5uv&C&b_WQdfEY|a&>4Nc=$i^$tyeHv57x=nJ z?R+t!c!ONImBKBpm4vb@sW>j?;bYUvjIQYg`thBix>x9@hyDY8&7TP1x77Sd_FgK~ z;wtc5c&kw}w9Y|P`#z6j_Dw!xGqQ-5OG3FhQmg?Uhj05wSZNEZ=|2tp2G&#QUKiB0 z_?j&q*FdzE3p?#APfKmGM|UK#TurG*BvQvLB(1c;Ksh7w{O67E)ag}t94$;ovrnF_ zTS9`gtliU-d&Q^CeNwko_nBV})vHnwuTer(Cm6<*FV5WDVxxKTtMgek%9Y-&Sowdz zKe4yQ2{kJXX8vyucq&^9t35$Zp{h-BG;%=eG(zW0x3ZGhxnc9fnu)?=GG&M#r+yr= z)@-!c?fhBdT|2~jis|yKn(m*boeIk9%aSrYyC=H6E9E!}@-@KoGFxJ21DdyeM*436 zN2_d(=fwIHTE@9-B$`Nt_12SZe=WVcw41~>)6CJKF3qwq3m#2+SAl$K;2#NG_|*JN z@V(}}bK&i7(@6MzXQkR-+{t|&si)p*Qmy1s-K~tOe##kcE^Q``2-NP4$rbo-6LB6h zKb17FD-%*4?jDvG4MpOm8PuFPDNW8YP<0~RS2^;=oH^y9x%;0AaP%?{X$wIO7q;8aN;jODP}#$L1XJMS1@K zhQ2jJ@m;)m;Xn98?K~A1g7p6Y2?97%R2LYLa&z*q+yEiC7|#{?b}p7H35`^-cz>$m6uG5F zQ>RtJ6)8qg=bb4^9PLi>j9W?Q^}9b&!eVgP{4}cI>ic>cQ&m)D2+mNHp(hy1(rHQ! zMY|@AUj}O41@R_@4~_g&;@JEzVP~ytHgM@WmBpRC-NI&j;t8CIV@Pcn zsR|pO52ko)#9t3QNuyutzYb?Qm4%GAnpMUB0FiMJxYRBF&2cPfZeoII5;VGq`Hc!G z--Qi=Yx2+HABb)3v<(AYT_;PH`D}h7O=kB{$t}ICuR3fdXGf<&r}<<;59+D-|t zu0LUhy4L;%YWl71!%2O8<8Kq)-ZJfuF*KTQhZH0+D(r$JSW{$Cs-oqH0hyV-tnVQD zhDU|YDp#DAHnN2ZOW7(=r5r_Ca*UK$wUhT7Q=F4(Pu;bz^SOR^JXU*(${ZSa7){li zy1hqAl+sB)Mwhg*we{BPW%nP4k-xHS*^~yAVvA;I8dBzs_UTt<*c({$t{fNhg@c?F7m#Nc;*#Qt0nU5WXvrBF%*5wY5EP6*(3 zN>5Rz|r(Od$1i-PiWdZwuyA_DswTu42*83nh25@+7S_)%_o!i`{ExE zc(VN4S;4Mr*VjILw%T=!SCY#&pEU2bD`ZdzF3p#1{aBXSf(PnH{1k5PN&f(9&xx_5 z65QMs&}^*jAT0CEGh5vi+M^(nSwT>xus1Uupbwe;7yLMb!#4LGA@K#Q5_p-eBuiLa zi4#SEn7K#^02|k5VKk%`jlM|26wQBh@P2KE%D6L!s@JDNrGM;<3}|80DaNH~Dl=U2 ze6pI1d7|sp?73qec}5HQn>)%YW?Vst44VJGG;|U{L$qJTi?hM{kj&_ZwZdW*L*QWR@QC&yHo*%rC(Y&#JB!x!R+>k`l zoCY9l>{uLbC!xUm+`ZMsW;`RAPm`Y!kHW_gsig=hJX)MrBwsHhf|Mei{n(`|w%PMI z@2lYQ&N0g4&f`l3iFi+GdCJhja>`MuEnL*OX8BTS$++7@b>142OVqV5iU}Q*343Sb zJ3Bj@m$Zf0`Cb{&I0f`%b((cs3ro>J<;d1FFZbtwD=;z1N`9oqPs@(WFt(M10M zWKB^LHi>3bP`*w`VU=O`SgASl&xebyUif$8M~O7syNhjRUme_dzd>7tNo}t5oexkt z6!1rt0hVRaWQfLtGDon74BM-^w2Jdw@Fm@)x7rQ%t*Xg+5DqwB+K|WgWo){KywhVvjYsb!G28w9%%mbAR|Eo1 zNbO#crFd6Xw0{XpD#Xj9JN>#taAuohJ;BlWK^h4oW(BnoFr= z;Q*BvoD6bT3yq@v3fGw#C>;OVtExv#RK(s7!PyHd?;pEcH+Hne(?mh-yrmTI54?RHEes z?-hB*-F_sROy}W^7%Rr5lgvP-dy>5yXdzYx+@Jy9oE(5KYky5*m-ej`7T`sAg%^7; zmAC8xn5qGgNgasKBLc9XE=+J7e&of400t^>r*Z1J100i|yh$dvtpJYl&@S8!LfKUh zD!|N$!THX1u^~Yoq_+aKt4)1EqK`K()v7yuKl2Y+xaoASvwa^`c41Du{{Xb9r^?^g zDJ3s@T0B)0rMq&vvrgT0ca5Lv2gBeK!q-;vDf#rRE^j4p8CX87a;GIh0hkY*+;TEY z2FA*|@IxtF@#gS8X_e98JhnKj&n?4LRdM{(@fh4KDv_7=hAyIvsm`*TWZ@`HClz?O z$z3$htK*ETG{kXUV(__EXNsrnGWQyoTn;L%B?Xt^VJSwWD7Z>0ahxUZwHYZv^2#nI z=ZqdU@wbPdSVGNr6hUSCUzDqvVJcQXB&@E##9COx41hr(AFaP<#!VyPH|@E7hFhq9 z9(*{`QGxSel1)on@np`joQF_S$yq>*uNVy3{d~Z!+Tp)lC&NotZ4J7H|?F0 zS93l!@kO-u`bUQDCD^e`s#?txD>3_#zz8daXxOrq^2op=hG0V$c&|yZ@g|3TqidG` z0BqB5Pzhm>1};^1qbUH0z^14Z-m4mhZJz9cCtt#u_(_yl$8*3HyXE z2Y@luRjZa?v&yIDCI%xo7z!|;j=5#Zw>cT=Yw#@l8B(5cjl@N`)`n+_tr@|%&Ye$g zs={!Zvx{EjqSmRUZ5jP5!k9`^$Z*(Np3bEugQrSSapt8~KF(C9PEe9+QEQqFN;Z9Z zpO^mt7(NJV9tpIx@jjCj`iFz>9!2x^6Mv!Id6Ftx-=t;t+DsR9z3QAU$s(F4vl~g} zz6kNYt>DY~SjQ#Jh3Qn)G`4jS&j`T#U8{o29l{_2HrfMiO~(gu{e{xwgH!Otb~pBx z*Or%dx0cs-(!?GaqmoGzW2}Y49*iU#S$5V1hYm{LeYI2le zN~>x#rGl(7wl^2?4! zvdX8N1qLSFk3lIIAC5W6&Tw&x_%Fg9HP$>Ctecy0=jq##H7zifYh6;=h*LeeB#18I zC0-d27X%pOG9$X5s&xMVA6aU8dg^*@nqAqsG34Jyv)ZxR#@_NDB$bdi-N8W1la9ms zS1rzH;~{FYjVwe`Q>L!tD=7Q)_q<)z;@#mdb+;Z?{{WaXejmi(Cfz8?t{PH&wIu!M z-L>rMr^{(wG^VtuwMk0xeyJ1YRbT=C07!@_Vn6_*6TkfDyrAky(;>>gp`d9-9bAiaSF!(B?%@#kVS{0DulLg$Eep zCy((*jP=cZZ0uvx^ota>xM{x9B%0x*51tqakwC%8AacP;_w;JwXsAoxlfA8IN!{~l zu8C@%w?~gl3t3c*lvgZO-RBi#<7c(o-88jr`W}}arEHpGZDwfYwAzU(faX%mfN)r3 zfW(aBfzKm3*3*W70g)z3AVno`N!oG2PlZ4v>3w2~7%1{>r8`Qg z1@}Cz0}^wNppQ!7HE$RAhC9{M?XUjBX{VyYB=D}=o6CUaLvwQX24uq*2!aHLAsV6C zl33>Pl;V@+lD>;btGDL;)uMh|BSnR)cN@j4-s!gOW}ea3+v>06y8SL@z84nLvP~=y zn^MUd0X*fIVv$f52ngTiH<;RojMURsxZ|dWD#aWSXvee(lcx-ssyIsY|^< z=THQNBh&5C8G@anMhI9CLHngi?~z(V5eH6BmTz{F<+j>3@8#Lw=0!>q_K-?Z<$RA@ z>#uHAb!WPls=nMjn&zu-tZMerX%{aYwdAh^s}zUrVq6W-7Eq0j2?6jr4CfWlX*%DC zvg+DY?;1b~EVjlS!Cf}Qu98o>RyaJWE&~!l03Sr~#iW<^7FTzYw6elwa9I=wK5Lv1 zFam`lFc$+0yFAyR#HkV;(MAUhhhnOe)Pt4W4h~#ru0ECK&b-=ERV1&kFDzE~20!4R^V>ut5c~nt^p}u1a(=~WbkaoN zs&cb$EOXyzUzauc&+r=cVffAP+DP``_>Sh@YyremXqwP{paI6^Odby>s5u{_pYTx+ zHsjzI>?v^sMpGBV?-JON6Egs8^$lj&ApnoMW83}l(36foHsVEIe0{(bFDXWNtl|<$ zKY6|x&8gl=En0EA-6q;<$tC(WN$e?bPZLMo=A_{6`Bx&IHzKO6+?q+rww2Smjjwio zPTD%H?aMxLw<)$>XYVzCbT5H*u;&!--FFI^(3epn5@&G3s z9l&sMMSRm^c^sOB)O*jI*YPiwM%DzRx%o)W)Eu|dsPE|zPj>>W8hnW0C=DVvkt(<> zNn8?fhQ>hz;PN=Hw#VS*jHOnRgO@xdPFIgLqc}Lfb+p?~N!zWgdD#|ePbSr+2j(R`F? zEusp+9(N^zqRF-*!!Fo0`Z1^e+nyKHd?%~4bI%p^uAL>_wXu{mQa!t*c>p@#Bf6cS z5w~&8e`FXGgN|_LO9|u{Zw!+Ip?*WVO}onN~0tedoyecC+BN2^)q5d#8jy zXjvuk1X?}FFxg+}I)#%oQ!x7^^IN>pyU5{$i@FepJ3%ZPoMOL^JVg33@ZS~YQ_nM8 z7A~eTiubXYTvcoqBNKwdRHZr4#zK>VuST>ZQV$B{IKq|hB{{xt=?tI59HSpk4Th?) zbt*y8RO!@8r?RhEIYKn5U*1%zDASbWqX$w__kEf_c76_i(v}|>ziJPK&|k;)ZDT~# zbsa(*h=K&Ui%-)p8KAgO#HW?#qod@49F7RU{0aT6yl1Fid_nk-`h+HS*Zw4U?&>KK z8RV8bpBHNLT1Nt)V>FT^h!Ft{`3eI!%U@J~!83JzOT=HcrLn%fdF?dMhJP0Imq(T| zk;$c5=V71&w!YBxzZLk6d^33{%(CB& za`>*K^SLp}1&qhbf&8$Gbpsg;k^HskaBl(S+$G03mIorjVAfBSaMusjSX?zuN_cA6 z>~?1V0C1$`tteq&gXPyl_UF!{`X{`md z#7{lC>G->OhE($`HUlrC7c}{>@Ws@{<7(21cU0$6FAnP{ zwJSm}dPYgro>zEh&Ur^FGDtbk03N5FaxvSW&3Yfgh(6WvE8xYljsAbeFN83#+<0I3 zS)LSgjt?PGv&ZU1d8E>++e?s3EOML-hQTZW$4qCAx$1cB?*9O@b&~489Xs` zRz(>jYm%#xw*&?Gy?DzQ5B8;)KfDsOyq=?Nyu=94T!W8na7QB@qAR?J3vgg{L?;A= zar2%DC-_^Qy?DiX`08<u#>y(jFy@iI6F0!h{?t$WXX!_ck zF(&|RCDgGi!TtbHf(XMNGlCu(ZiQ-dgGx}8W}A1jgI4?9(@%8YTOYCJxI8{-mg6$~ zWED&{HicX@XjvyJRbb&OJ2a;osnd46X9!7ItDjSRaqum#k31I+x1&1EtZ7!StY}h3 zf=9ctyN))!uwsrwt-?VAZ5zC)tfyc3X~)3YXnEllyXLux$D1202&B4v!Z%4IR*A!} zlt?9!l!An*&)>fS{8qQtS3V2WKxy<;ms9ZjvH7m_dB_*KabuGtmKP(=Tx0ioi9(@3 zubuulcn|&%j~Pj;X_k>EhdfRv)S!*0mfdW184EtIXA>&{8^<7?`qeN1Nn=f=ai7w# zc&K9V)bS9usVVBO8#bjEYySWaNyhSD3y(`9_)CehI{Z1E@!j}Ui zW|*zxx1SQ+{i=4#xSHJ_HjJN{kU7dqvISwC+oI{*>%(G~g{67y;Yeg?o&}QXa$|5x zyoIg_-N4H(-x%CXOXZrW=tsUlA@)>*vdI1vR6KP~r$7Y87m@^hrQr0r+Q zuV%H;Cfu!cZ$7?Fo)nUTPV1Z9x@(p$SF+t%^K0d<_D4Bvim!hZFL0Z;t#dQ8y%sevbR?;NRHk_g`#7% zNCBIINE=GF2qQ0c%I#@)E8V2;)!p@5uGTVX%5F~D-qy29>!q|?ZRLMTh>%5Q(n56m ziA)*v~sl< zcCMR}cWXwh`upAeQt~kp4Mypu5?Z~r%u*`aq;^pTxkgssDQPZa^4KWaLk*=%VYhs( z9M=&GArnm`w|m+f%QuD_e=8iQR(VSDGE}QKIqcOn%IY@Kp}n}8?6Uwa<+>kqpWUS1 zO2e~Z!m|t|w&8%NP?NQec?1elZO3l1 zZ+ltUZ*6wIx9W!|Q?w;@qDdyTZCdWz?`HK@x0#BIsK;$?Y|Pu8<5V+CZJ6UYAzju+ z^4)Xtouu$GG0hi(R)TqCRy(H7*l%KaRbTJ4@w%$)UNTlq`M~nP$y*BGm$*puvXZWR zv=?A3fdG*THPfhg$RuD6%tu;%rvt> z&KX%pDxi(n#t3ZnIj%p>+*M1dU;!kNx9*;SvB?=Y9FB*RT_&_*lKSE@>kpr5@y28% zMoP2B3+)GCZM+<|1`iz9DIJ`Uvu_J7!Z%8cKIy<4RO5LBjm1tj5!a;njth?J}dR{I$&x)a@kjijSyS<<9F_P1}*6qs6RnXT}-4ePoy7CDD zc*z_CjN|Bd$E_@@7SupS^&d9ef=E1c=b;$nuN zy{zr7hhwXTEXeA^4YZO7&QDNz>B02pitPrkCH=a`btLxeEt=jtyL64NtwCgOG6`Si zSKNR%%oVyf70*Ru_L9gJNZmTCGC0EYB;`RF0B1dV4)o?(<5H{{fcaFe3gbUEaC5=H z>Uv~xMO99+QK=Oso3*!ETSm3Mx7T2$DztAXHx(@|wY{D7x@)GZs`Wh2#y%49ea@j{ zai-tfYjN*peO^HhnX6eKRoNZvDdgMTLN=3_%*`Vi9&f$6x<3ru_@3rCVAV9_yhA?8 zZY^#tZ;hE%Ie9KErJ4}|kPj~2XA>%rBae6rIv+B0A-6a!*J;;~&j*O1O12%lzunrTWy^1A3W@VVQL@!Ep3W_Mt9kURh_I5tOW?N2BUsyS zI5=P&^&3D3BRJr3A%PY&1`@kK=?fi<3Hitika!%PMh84reU`C;W4J_QNcI3r7G+_L zfUzV1GlQNpo@u3RUh>-R)_qFL%0m#dis??BE^>U^i)M(l(;Vzs7IX@TqhZEt(dMli zCZg<>>AEFu0#?`Cd*Ww zb+(%7M9E~gS7dpea7(0NijCO-1CG8%k~qkoYiZixtcwcf;mBpd^A&?eKm%-pmgEK) z&3J!`tZ&Y%rt6k>TBQC^ideMU%{?_A3Q06rNfD&Bx&GDBF6B++TtTMlu?bI@!~R*H zMS|*MZ);gl}p5=u)b@^BcBHR2s=m1)$cC^$P^ z$DTDKe|4^FMOo`8sLPdGSA9J-hV~Sw)TLH4RU^$VS#nO4zSMo&yESV|nmo^&-B#B_ zSJBv6+}-I`qTf(RJllI)Z?cG*;aAKivrMC>E=j9k=OjM9ck(yXrR;?%69j(t8^8Wp{Xlv{}i5|1># z3{oop01Jh12^hk)F*JxHN4Ynav&52s9^8wR1V))xmLTzEdY0YtkX48(Lg9GR#W#K% zp2{sJNft2PMDbkf6IuPIO}LewF>WFj^E2C-gFD{mFgeQ&5t zG;KoGHxH_L#F~ z)15ax9qgKlR+7D&cD|JIOurLKc!}d7g7(zh@ZQ?32`4{j@t$b|;?7s`lv?_PEF@tQUUfL0+F>srX*?-%i!ME39dW4irgxEaZ6tp%JjTw7Zl^ zD>lO$n2->6$dTZn;&rbK{5RC^7B3J(;(2YMy>+xYh4_*?CNX{Mc%ZRpqO_DUD$2JL zPVBg7V^rSLjLg(&PIF$xO>#!ABi*M)?#<0fZobaZlX|tYth*?^dT@nkSLAMUr-hSs z>Zm0ySS3DWosyND+Fxb0r;~Vt<7Tbm5A2fCc#lQA)3sQaU?R_-`)tOd!V$^JgpsOs5 z(qVO2Z(_KHCPq|Sc{IP=uxSL62MV?H9Z$pG3-9jl>~wt}Qn0scyL;^e#u{gcZgeQ` zjnH`-$5yt|9jsAhR!HYCu!cgDMIj0^@VTx}j;`J+jy9CzQN~k(t12|=Q)x?{m+yU( zX)b8Wm8W?39ybClG1Do@$_S~7CdPPaNqCCwg7 zuc>t(*vCZEwXJu=ej4!K#GP8^&rq6OPQzL7uD7M@wvyciZ8|+GRq*YP_71;hiwvnP z#hv}!{{Xy=q&Ss{gU7$KZ^eBB!_uOBF!6onsjukcQqd&UA6VBkdsMiKb3v#O+@_SrvDn7;-OuG>ZbonPzbE)pGNX0K}PY)hR!lmTz7V1T7CuLGzr11D` zBZYb6^9pjETgHrBlbud}dBstlB5-k)B%;(O%M0Eyjrk+_=X3DxWsRy{s%3P~TC6`qpT(Kedaf@HRiV`|1WxC!N!n8pp=C-!5z@XOih*1Cs@ z^nFuM)26=gzx*H{6ue8}{XbZ?4rF_6KF-@&vb395vD^oQ z!T9NGqT3IM-WSp}X>D#3&ee3U3t0GyDQ&H!-y~6LaB5K9%WZHIY^5})q%pDbqGl=& z)Sn6dCTiX?{>Z=aXYA?W4-sjNA(O+J_kp!|Y<0Z}wG>G1X1mZe=(Mt%kV7QiRq1I` zIZ-3u8i!TYN*GwsmJ@BqEv2ZRPY2&!nS5KKHdwoLQOQzIqnkl1}WpyT(#*KR0 z$2$Izt!iJhR*N_fz5*?D3^v z>oWL@RPfEtmSr~AdKu7lIQCuY7I#x`(KS`Nx3>{ZtJ#Z5VY@Ok7V=y*gN92nc|V7E z=k_)DWvf_?N5kGfy!czG-5a2M72;6ZU|m`b&d?oSM!45B{WM*ac7oxIu+1q%*&9fz zK4%qx%QHMiUx=Ym;HzP&VktPyV^uzS+>T0}T(Ycd(WUI+$m8tgMcGDupV6$xFvH-n zm}-=vjHh0%8l^eYR3Tl_!$zWwD)jMRxUD$KQK+h^)2VkY6_3N6FT>sp7ouCQ*w5lD z00)pgo#wV02?F&W>0@+`tjaN;LPvk0b~J zUh5arPWK5V$J!!_-f3jHe6Wl`G-PpKWB9}NANZ-F+b@Vmjr?~Wi4>3z?T-rhuHVF3 z1nwc0bh4Hx^y_=Lgwepr`{EIRz_g%{E5y7-@FU{?0Euj3PY?V>m&3NPT?c#HR=9%d zRFVixns%XR(MpW)F+aSD?4<0(e(ix#!;RsLPBRgNl{{5EL}}KAWhxn_I&p-l%E`G` zsT%ls)10GeQiN(#dh%Je^}y$p@N{vtCr+gb)v$H2N;NP_6O}wlj4IjDg?c!ea-^pj zQmHsnsTpZ6btmwfct_yHoVQbt**oLzmv&(*6~(jOO4g;94J0ci;qtCqJ5k~SKnWuU zCcRVPb+5x;4chq2R`9RF&x+m<)ihlI&E)v{>_=gK_abM8OJ%>kZ#w1~?f1^mt4kbm zY+?kMZ=&q~0A`PhdQ4Nvt9)$uk0zpR-Z-SUShV<1oG6@I%(o_GR>sKQNK}Fcnh#$* z_^0rr<2B!epz!^*#rKPmNL%efOZfEtM*divFkH!M(3@b-8I>G=XpnG8UO*jq?h(h= zr%n>KE}dz@75$!Rh{ejCI(Dh=(!@qGsTa#CX+pG`b8>cR%2;Jt{#%E|{bEvv902M+wu6Y1LHf(^68LUnNM>jM8fIij$0&cA7ExXW$QrH+QQP{v?LzYZ2-) zBf%D|vq;iMYWHpA!vk+dSQV978A>7C3C+{>F8~{8+gH~7BP7j{EV0~aYq?nNSv;8E zF$l&4jH;x#+}$%?gW;=9Z^GXN{{XW*Yv7F!RMhkMbbX{%I=r?}eAiNUQhxm`RS7DX zher#Iid5=4oRY6O)2|A3xs+)0LTa3)I(Cb4hbxOqmBlviS@?Yw+%0e7zY7TCUH<@Q zhVIL3st!MSHvRFo56TsR#`F9&g_dEwFSY&;*QN8e+qaz~L29>lGN+UBLer|{PRA?Yx}D|bpWzP+_`AWnR)Zgkyh|m#y4Izr z$pyxlZ1=!iURc55z1C7e1F4eQH=6$d{TUx;&yIax!kXs3{{RYa^uG~}F?GprV4n6p zEGlUh@hQ1FbHM~gNa9&huT|iNdBiLcyvOsIQ{AP2_BkFtv?*pS*URe4relh#oGQH1f zIISC9F8GX1W2!5XNLd<1c3gqDe8BBq0PD+R6}{klU$pDmvNN(rABS%)5m4<7HN4RX z%j6t^{lGJh{j2U<4}zWuxYP98sm`qP&tq*gvMu7Ov&fs+1u*9UnDNJMag2B5oHso3 zRjFa;7}cRp6{>T}5Q>EAI&rk68S^&N=T=tJSFx6V#dPurVe4XHIa04$tr|+4B~o1U z;Tn?Wim446lCw>w@1nKOg`v`J_O|;w_f^QlNg?Aqv4Z(HCy)j`GJ4xOWQ)hyFPoz_ z8NeRAlg@f^oyYU9yNAIq0y2qW27`HA?afp6Wz*1AgE*lLOErS-%++wMLN zk50O77Sj0_aN1bSi~vdRjA!pJaslUVYV2BN)GF;Iwd{(?wlGYL12I1^1e29H!RQ!! z8vEFM4)8$WUTc`_P26m7yZ}FRGEPo?IO7?m9|OD&KjrIMBx8@YAS=oL0H$ZC!Q(uW z$9ikSs;^IPOV!nl+Vu7oUc2-${{V=agSwQd;#lQ{XwY>*oq>^xZ+3 zPWcEf!^;4P2hZ}AC|fz;51WEBOpi^~-E;k&f8+ta6$4~R$>-%Ea^3NkIOl=K=qh{@ z@Ic_pt+*=6N83>ph8QKW0|Siu^!4diq4+D{6^y3cVTl|OexUKdBlj2?1d@0>DFT!5 z^16$rs?d~Nl$(`WS4}38PuO!MtJ3K^-KS*JkBQhBOP*A*YH@_29$GaXl5uuwSd|BM zm%Yn$m6f%>z}h~GX>}|A0B+r1XtwCeizGI)+)XPG7&4%aL?g^BtOv|6Na_uHWsktk zHsa3KJNQ{7iM&P`G{8-1ylgZ%x z<|iV;V6l_H)uT>zs7BQ$r6JWT|5rjwK>RB$XM%7AH91@wXYTpjzfImhw6SF!KUCWkRy;`9ol?Fmky7 zw?Uq9n=>q`l0OX3HhO|rlE8i3?ou!gF_1EGTzHJ10-^5Ef_Am55zF_b?Lj zYBvTeNTFl8V*rs1(nuE}M#W{`8#!L4RCjeAm%4nbpGdxBm9G^kD6g{L zHtksOT}Q!CwDMhPvQ4GDq%^5+&Mku}!9QkG+K%bJpER!(rAG-S2qZpv3`)8=t&%Hk}CD9vL{V=%aWda{&VXj4?{*~8(C>9|Vv z_m$m9`>*$Wt*7Ik4n89IXW?IhmqC^-TF&Oz#QLqKp=qc+-QCWs;yZg?HSex1Rue3< zTUuLO*eo;L;uUMDRyN<~0qK7ZwGCI|r;2=8F2AYjcA6cXzL74Gq}a_Jgt4WTMaDd-D5jv4VCDEm~R zy`}V%O}M$X+SQ|s{h>6td=aYZHy#!fXty_7H-)tO+wC4{Y_IPkxW3bxNT`m0~NL_$_49-1ziO<;G?34b+m&<)@z`pAh(e3pL3brp^c^M{E{3`1{3L?uFss9$!86)vVWF6s6L?a?Kr`vqLjdw22m@9u7{?(TG-1K!PZc`TF8#WgP!qVAef&nDI0 zoUw4N&}X01O;3HR+fM{|j%!UKUFq_yWzw{!e!yGd*8sLaNxwcg z5_cq;2ZReL7~3RzhlmIS9F|bBoOI`|JN~9>z#TFf+=C3-eVW4A+QC*wAb@z{P0GJF zMF+kQ%JIu^;(C!*P?y!(R+ErWC?{{|f zch%VZ(D>bQmf9YdVGba*3GrSS<5RU!;PD(jOi`-woGC<5Fs#Y|2Nm~6><@Lf_I!BD zg+K6^_@HNyHXSp=M29D-2O#I6Y;Xw`@E^zMlHbENQ#`J2WARVKO9-Obm2{KD@yjfM zfjN;@CS8OsL1)h!Pu>3juwK^q4Dg;y_|L@32q1x-JHwWD*LO;N8bIB`Uj=F zX3tMJ18gb@0AYa}iTaH6^d8t9FeJv{unUOE_aG6EOk|GS`gRbat1M+{dgqT^TrlUPN!ARCbqt^mbYE{e9zD^ zu(aZ}QRi{jSMj#2`)Jkn*#2|BYV8M3w*9O=F!;LSHoMgtZ9cOY$!!_n zU0j)!T3|P#L=_wf7$1@+oej0zi0at6owk#M=58lpCm3fWU>-?0Jpiw~e{L@X_`AY? z8+=RRU3W`(JU#IU$E$cpTaR;T`ixfarJe4cXDW*ht7RlH%RQ8Ud5~R0Ev%E2xL7_K z(PXrnO4KyztjyPQNq=b%m4h^<_2lxTjfugyw3*sO$yR85usu)phCu570A%HEtfeVa z%dikplTI+D3_Ujp#a_xP6XsmDZc>wO?a2Ip9_dFHjZ~o(8Dg{txio*m_QSk#mq zCxTO#GKaIDC0f++6sI>RH$tU0=G0W98@8R{C;47KFO_$i)|EI()cV|_oMhuVYINyU zp;|HJZC0fuly$tVXYnJr_+zWj zyCTX2cUPA2#6e+Q55ntR8%_AJspvj8v@2z%_#*F1@dlr44Cs(t*+`-GNNwF0?9wIG zyw4u!+Fh)Q6gi7Wu#3Z5=ZQ2;Zr=WVGRy4=eSL2e%YA8T(MzW38tj^UX(X4H5?x(d zO>-Phl2|JZTzSi%_ zTjJ4aF7FU(*0ZQsLqyAN>vqL=qQZ>3q*A*=?P5f^KzSpF_>B*Ud{g0gO_Uef?e(SY zl$Y)Hi0*Y2dv%FiTtH-NnC6I~%q)TT4XUKzSJxgo_&=+`aR#NJ>F{bAF1w;>w!R|K z;*gnq$)$>GPZRiZM2=59NFa)M;+$Gf1iEgdlP)gp&27v3Gx#UL-ZQZH!Q#KS_^ZUe zBGmjHr05c9@szi^L#F9k4x_BDww7J!9_PxZA+svfK*CI$(@;)%b;W zeCIdJ>*e@Z)yKk9##gUSIE*rvvxQ1kx#`AkFA*Aa;+<-<<@OR$b)7iQGB0P9;;{Kf zSC-JmV__TxX0ViKO;fDk>c$ml#uX(P)Qt(wZMso}W$kYzOPlg){{TYQtkBP?=o;Rc z3(vMW^$jZi&ei2*eX&J%JQ2X|%ebsdDR44E;1W1(PfoXx$#zi^;@VxY&d#b4T}I&1 z?jCBfRSH}Xt&_oO`iJ9&g}>uwscqr!5Z(BTK=HPzVtfuRrkSmgFYn;fUejQN8(4I^ ztJomQ!!)s438dQWfg72h;19(6pz}wiTHITLgRH<60 zxp!{~vQRv>WCP}jW!s1I8)~*#jlr@=AT~f9Fe?3}?Woi&e9MTG4N?^WondgRaE*mV zWhH{CIKkWjUUSd8c-KtuH^83;>9$@b(RBX+8GK>!K>JOOop%(|cyqy)s@ZXIEM*1l z&7$!wvNUgbc9NkswvP?mo?C6>Uy2i7SwUfG@Vh{3tC--2`#-{0H!{Z4Ka{RsYxuz{ zBZ(VsNZY|69Q|cUQH~C+D%gn9m$0g;B~Ddc6)H1LO{u8!#W_lFPVu)Zw4INgg&L1A zqgs_UIJ`v}QN2Y?*7kL%wd~ZXxj4#cLNjeet#yr?`W3!Dd?MCtq|t5sd!h@FKFa?9 zZG!&NIBqS`A}KGQZx}8dNTY6dY%IALC%w_UQQ^H}+TI->#5!KA@LIzFj>2gs+|Wd- z8WiQ*fC^w|7)}7Mj(jnF@n^?h@Ue>c-%s%4_yQE3R?)m6VGs7Zu(@_XWW1HE+cy6I zG?<@0U^{psxqtXez9nA#HGdsT<8Km&8s3|tTWRs!*~4thaTTn#9WTP%gClmEY z#aw$B!w~-fvQ;Y7vGu9C_!>1YhRf?JHQM^UT2&(&HRP$jd(NcqC^iv zMGdZv<0<8doNfvb$dVC}7%~mGl12yeFX118r11u|;QeY{SH-%Qh+}(AQ4;?ETM478 zMQJ7F{P&Rs7`L{yifI6R2V_{mFCwY^EYM`Uw*8QPAxm*ApJ&%UYTzx!&@yha()l1LIojnqjq6$7jlY~EQ@b#m$ZHGrX3oTWn(R+le7wXIi@tHf1uaEh{^ ztdy>s@E;K+)cy~$yOM7@%3X7GHwhz24D6bNqo|WO5~HbxNTgu#Iy6kHvjXhc`#hVr zC^5M$_t}X;a9frNNWsTYdz#4BuWx4XOz~U<*=MO(OK7kSwyhP-(44#g;1nCr&z;#B zU|17Z=aUx9NKy(AP6iQK2wlLD#z?^jzXHE3&AI1`tnAa3RVKQ(I8vSL+kW(C3thi9 z&)N8Ik{CI|NjN%*HDIUpts>ko6Xl%2op8zQid2mIktql=Z*;{3;`VW z#d$SjB`U7&GKEOE$}OgvtEHN=RD{)r zce_@1X#DK>;qVgk!Z$a%=Z7sOo5Ig?J=N8eF}&A49=CaRME3B+9!ApQl0-=wFjm$w z45By$gnY}O>o@uiq?b17EzB}XqVB}J&|2!Ys9Q0}V=BoajI>gWGLk|#Qq}u-kwZSW zr$cq+x?X8l(aN%@k_nNJZb?;x23Kq#%AAriqnvyZ@%#36o5LEl?}+>pU}w;;oZsGP zmgrvVO>j3|-Ppv1yz4Mo9nnh53zAkj7DqAu<-i^y`$WEb)?iW3iRtZ)%WXuE62VaDN)2`xlI_$2I^FfH!r6iY0!gQ@~=YAozRn; zl<7rtVVaESH%U0rlft*Y2Js$^{iUaPTH{rWI!AwGvZU8~b;v|JCrRb=%H)NLVhYYi z_}RAtSl%J<6^^L(6Zj1TyIE}EjV$giozxbc=T>(}VvGW0a#d7t_!aY4g>~IW!y2@A zx>eE%Bn2cAE48MhZrnAsHxehBRsPPoxi^bsQDK2_d>L-Vkw1q0_o!g7L37+2Qs8K9abJai&g#hXEWD#C8@s#RQ_EB-9wOrJr6??4~x+L{Y z-L=s(+NXx8Mt;&)tlLkLqmxOu@pW%y%Nr#6wbtf|s7Yg|+1QJDvUrkWLaZB@vzb6) zBY>v?Rau*&f^aLd8ilEeBW*$DkO2N=J0!P%wBctu6l88x9Ybc`=&Z zrY^Y>OtCH$kRmzA!PTKkjnh>nZdk%jQIvU8TFNO?Nwx7gO6}%C6D@$Lc5T@plcE?9clX+}s%_I(@&yy&hTCF&wf>r+Bx-)>2H#g;kDe zA!$OV${F^r0~PsE@QTJ84~kv@)O7YUTt(vzKI2T%V~i@uWwgAvNM8C^PbMiF?GhP8 zGMKrHqZU>_tG~9OxSRG`{gNiQh(~iDiM}}6&m1hb0@dO8mE%P*#_|M71Q^&H>@w`$ zRxE%&J%zlBE(2Xt);?&Z_ zb5VrnB`DKLQ>l^isLjPF+E<*TEo78a(#-sIUlLi#s$9<&lMBwS5KhorwxK9xU{Pj3 zXHZTKG6Q1=uRT?cuYW$_2ZwJ70I+#LgdAfbT2@WRCxE1$ryLrB!UvlF0K^lGJ}o*K zHEHFsf-;W`c0|b0MH`GhApj4Z6D0NGq`aC|3WitMjky&|E*K0A*!#n-20$L;HTtzW zRjWtZ%5F21QbEq&;zMcHz;nvwa$@f2vy(@<3*8^#rVt!Y7}6)4J_ z6NI@X%$Fl^akElMrks|(BGtvq!rC0Lmp)i&ZXK2^u?5|g*dhROTa1jALXS=!-}BO>l-R#q(K0m}jj2p!J~NWzm;g2Z{3lf@63aI((NnI8b{1!Hbb zdJ%!1t%_y7r1$g12AHwlPdtef5l12`Pb2-rNVC1ea?ge0HFjdOTg(oa=2h?P3BQcp>{r0sa}#!dU`>9nu<1^)m9 z^!Ul3d@K0v@gv6`B#2%lKLUJp;avjHPPYR0R@b~=bD`T<*$JUQu{%Sj-p{^i5kz+K zVTs0k7^>)c0J^XVg<*C_*uhBl$(s{VIv4B@+ApY_HmWxPNlxu)ieuV4*U%GYoOcS-A@OKJ|uX9 zQiAU86j`8#<4D!5EzDMt0`e>o-ZLyFHkpFqmo?%#hrq2|T{2jBg2Lo{#ggYu)h%Z# zPJGWV>}YTXN!l@<4@&nBjF%GF_&eY|q9O90FBa-WMoX`iZX-tsfStt55eUN#*#iKY z`P;+#h5eVoJvQb&Ls5p}{{Z53+P&11O1EEUIALrhl?d!) z`mZ%8W3yV6VMQ>rpR}!p|X|{i4F&j&5pcug!%9h-B4B(P0 zx&4Ce+Uxee{g$o3Vkh{Wk{cr;*TKFhyxMWNf{$#4mQ#JN@`MW8Eq*_ z^SW;Ct@%~bS3er74iT-2$Gqz)&as&3W;ppz6_;i{!kVKjT&Ylp)um2w=Y(lVN>2XL zQdiL<;EOF5cr^%aE)j>>mT3Wb!;vJhv?MmyVgn?s0ylE4jDen*q+8+)m?9&T86Pg} zmUGu}Awp-a54j&f{9y2xf_yz;;XCgKT1gW4gk9d7wY_`0OU*7gm_TjBwzjgyl1n5r z2Xx)GGNl1E;IhUy$N<{0!lbZVg3M3K2_vBgJm7UbYkXZQ%Mm!$oF!2xrzkF1{0XHM zqqUoE`@bXiuMeo?_%0p7tdfQ@j$L07jKouhKBQ{mok`bJ>q>KkQfr!m_Ew6tV`hr* zqimK@wN%PZPSpSq816g*-2BCkbJX%`(N0<8V zDMiXH#YsiSnlWvq@~(%h-}rY_()>ZEi5C9=NVzw$#t0%rUMGQpJV!J+St02o2ums0 zgnf_WEdxsUz3{Sotv6sA-j+N;;knFWdGxJ%2t=@0Nen^cd95#_{>{C%+Ro+&g^~X0 z=Po~HjW%Nu(>!x~5OgtyywdD1PtIcs%GTP}<_dQbh>mfzGYnN9g?I3HGseCs_(iDd z$*EXAqVZ@Nn1!t2e-K3yeYV{#o=HB+m(zz-h)(3u)$InVah%M z!ODA0eIb>imhEjWyu^v+y0^+p6LB1|8FK`iU*$Ulj)QO|c^_c@)1ME2v2QK>cWq@9 zx_+~99fyfoC3s`gwQ(D@rleIObL46zB!=mR*ISuw*K39>K0d#*gUONOlG;mYM&~ih zaUkE>)CjX2k$}p(xo~sGIQma$qww9O6z;cat81#gy4z>hO@9rQH&JswY7M-Q7AAmL*vx)MJh~T^t3Cm`p!)un7n`+O3trz^sObOx#=C z9kRIJ6GeVXFlSu3kV~+I$Z)%fAxS`4RMxXuTTN}XW!)4!A;(m&Wv%F(%R!#!)O()Cv7qt$XErx7ZWt3uq8(4J7aJ& zk_ZxV31(ahH;ZV0b3N6U+DyJ;`H)W662v4b^FoqExtyw!s~WI(`BWCjJ35uU?D9uF zf=?;hzGb)B;I|iGed$(aoPi?%qy|tMVZ#HFRZ3jym$13Fy_#E4ioR*JjoCzCG*OQ; zXFL;RjHk?`qa_#3 zXtcDq#dNu~vbxnimqp1mp$+6VtTlwPnpo}{5j<$o&GMf<8GO)!1#z+AR|sQWg*Fjc zH*hVj^o7$&ICjcpgd7p`$yh?cl;9`NcQ|6`Jbd3i>$L;2@zeA(+#|W5#^FXxxmOH zzeADfz{J6ghU2iQ#?na`IpiGWK_qe0lg~=U@n4N}-wZ{0dw*-F-$68q5Q9s%6Uv2M zfp;Vojy98c87f1o`U>Q%z9SuBz|(vi;xsdju)d)S+aZ%_`JXJeK348tNSBE6%6J6u z_;HQFU^rI|3{7ZKsZ$+~bm{WWb*d>3S+1sv*470w&2ua5 ziWt;oo0E;?;Z;Z9VyXODu75$cZGT#e#aD4OHWp~s-WjsE43aYLEhe>aoPPG@-I@V_ z1+u{w4$aKEM~0@=+6(^x8(k|w6Paza3oypY8AeLaG-y7{H0n56u5)=ABrX-?HR#c= zhooX47mg!UjN~X0gun^4Ny4gtFuZ#6oc-rLOl0Fal&es}(vqAhPAl5tDnX}Cbz#kF zG@#!+D9ZIGH3`&FP>dhJxMA=Vr%H`#7_4n*x^*klllB-|GhDSPVdmi%h_6vzolHbh zp-!8XIx2FUs+o(cX|P>fS!#CrmYF8`BGYdqA*?k;Oro+*v4E0HqjJT`$;RS&r#->~ z-b1hjK^bD$CmV(jd|;A&vBzDxZM2E@ByV{WuBn2Q88vq8c9fpWvU|5} zEow(P5XSAd2Xe7N^5FF#j>qfo-t@Nmd{P+S=OGks zPcWmi1A>m3%CYU(=hCAMXp7~dBxPHb&wTNYdyfAAbYq_Nw>q|$yY)-tnTw|=yEhwK zrJtMW@)*&=5kjEc2n@jQZkPa$2742Ld8w8OfLBIB2k>K^-G>9jFqC!Ow4q>l$zbG`QltVtWjv9C-nsox!tm-^w0h-^y{%|EnQhk* z*<2;Ymva1I+-dibT&fTOR$F$4BCN$DM?33g&S$uELm4biK2>7*&jD8jn3MA7Zfl~O zNHIpTJaQ=`cu-kcLEwU*<#Kr;fa#o99wLGwwzj&l&{@5NlGuZnpaxf^e~n2 z6t6mU9h`Y&oFgd8Kg%^JPBKkyoObG)Vp~TPwwCbS#btkS89sXpV3zMFas-e^BS|z2 z>9D_*Id}5By-F!Co&SppO?1IzDnN*`l_V>$wYcH6kyx3=gSlNkS zq0|uFI?@>CRwhYFa>|9uox_Z72P9wtj(T>@XZWW<{{V!F*uyOPhMMuq9mSTXrC!Zx zePu1XthVju#Uw&_k9e-kz7@&r6tQAcB0c$cIH|nx%6&HE5)~?P2XD` zl&ZI7IjU=#_kzDJ?Z0QNTwVEEO7>}4q;&dzkuB;A8FeUZFA$q37*3KZjD}oe%Ly9o+mi*7 z-o%#Ad3pBBsFF06<)DTSKg%0LtrP%8v#?@hWc%G%rudk$G=1W)42vbk_EBMJk18%3M70l2nD-wZUFfgXU0^T1BX|+G|Gc?|Z8!vU0Mz z-0z_nRreg}UhYwp?*%TcD62(E?XR zi*upf#jNR(Y3xY1u$gqJZlb%iWGNlVaU#S?xX3YvA5{1=#vkyV=(kN3wYHgltsKHB ztfaDQro#zZ(&WV)o=|2|%p3q%E0L8I$sA0p%58 zg$~T8e690m1mwTY1~}ip3KR^0D^g3V-AdkD3yX%iwV6D*t>?tH^GA#_OA#9#TnwGz zn|TLzO>`PYk#z(U&8#ZBrWzQ++qqODub!l|hOJtf>hbG!3%Wl`QYGYd!742t> zuNK|gbt-#S{>+>9ifP|oZf!noJR4tzUJ<=vJlYPI_KBi4``H>5`#)0|h%ke0dLJ)$ zP#bPVPTvK*4IP}iZ}v3S))UJe#l^m#tn0dbGEEoElE$`rlnDyw=4FRua-5k_j&peY zOw;sKjkOE=8^jT?7TJnfmQD#T3U8YzMlrNDPH}-=CGk_^=k~UfZ=rZsUbfM73#)?$ zp)KB`+FXXruqN8lR+1?oGwx+#<}48L2DQuTjEUUQmLmSC)2KN->M<*I$0oyc6Nw9GhJyS=Ex-%1B;a zIz4{=Yjt!Wz$Fvh&2XSFQ;6n7VlcphMRdL|@s73Op9$*P-hr#$$FA5#1iEZd-b(^q zvPrgBW){+0%E=rCNfJesWsX%sA8WXO&z}tHy5@-2T8H+)y}!IxiS=uHm$drFRrcLt9UHTEWOU5B5 z!RYRvMO(t$4>-yH|y6+Q}~BGsf!7aXk0X zUP%+h8zgaDLSvU|2WcKmvHCMd{h;;l6nJ%Sb&U&0@pg?hiZ%55y~W}?d2t7OhFw1H z#QA|kUD``COBk9so695QKavx8Q&NISF7&-h-M6d3HJtJ^D3+HJJcbx%xd|kK0Om*p z?TFdi%lUC#pN6k|Tcz1gqZ|DA#4X=I4T>ne*$ZQ+o_e8mMql!%-bAmERh z#qhp$g{tdeaInQvgn4C7q-f!#Hq+&r#88DfE=g*mDaK7cS2ZOBeP$bq@|;yT)2W!e zJzB4u+?{MhBNWx(>DF~)??t%D`#wn8O({m~{WH)%Y%N>BH2J(^IvI+f&gb zo^4A(mS`r-6UC?M&8S;K#uIS^2qTT9Neep@8Ws9G;a}~g@Z($5V?Pl*IcMPSwuF*P zWzjUb^gTlDuIG+R`6hcMxwC;|NW`}AT*j#~ODG{ER8Pk(J5{~a-q1&(T%HQH3;cBRh>Q*wkN?(0;oHj-S^?e;h< z$1Rj03OLL&O-0A|)Hz#r_f%bI^2$!}RO3xwRHB}T^hrLu@Z-g4r`*c=UE=B%U)!2Y zI%T$z9Jd;Ex(2_F1h}-hmiEW&jWo9ahL#xPX=0igV_8vdKWD#$I_0>s)2-J^7i8Ql zu9}_8Y>`8}CQFS$;ZK@C(Xzw{0IHAx75wSw{{S5RA?g1B9R3aKRz4Q+y|0MA6~n4{ zLrT!DV1XvQ(7a7;ai{p0+?PQl_waar>r$4&(jx6W%0q65&mcqke5f0L8w%e zdDpy^SM2S!k&||lYu|iD`we^}@ddS}lP0@+;jL@!EcV)tk9`#JYEeEAE!LId7`3Qo zd?1cktv<@G2MW34!TeGG00j2)#<#9GDfnJt3c>9WZSLw9j*w-8#AK$2K)66i$YNUo7pOiE*H6%1o0 zyxdO@XE>U%o;EVAHrkA;&)TIF;**!Ml%(Tj%B3chAl12Tr)3Q5C#6lojw25UK{+_8 zaEBso$welq>f4p+(^9rCC%Nvx-_We3~_y~NaEfI`;p~_C0O;rnb6mr6c730E%A^ymcRh zAV~fO_~S&?WYpnH^FM)RwY5zy1!*0(kp4t%B1X$R0w)Yr8Qlp}^Y@2FrQtneT=15& zeW+gP*Ipmd^<6GI`#3CLOVq8U))!IH=2$Il_f6#7+Q@=tc4bVA5aqv7?f(F3&)O#0 zWVf5f@?8XGPbX2)>}3u)Q%knEQc*tC%nhic0ktb-(H88sC+D;%lgVMbIOaad{5r$&}8UdA(;cCX1= zla!^)B?jXva+Fk4lTouM@pfMc(e}$0l`5XmN_1~Kq>_VhmoF-mRIK5nZrr_nPvED9 zmha)m!|ie?MZ|Jwg=DgHSs;6PZtj(a8Cd!8fOfcS2I`~?SEAkcUdBn7*jhPDh>CL>U zC7Gwh1`%^Tg@}?@Ih`Sn0h98^6w`hoe$YPzyaTQ4x^}nYNVI4?O{1rZZ13zR`&?-y zv%~)Y6%U5~%w_vstoodgTk5tp!Itv&=}fT82bjaitwT43})A2MVL9Agi}L zlhk13W18*!Vetw6CwRx=FOTkR{?7g=@onwSofM#}{{UsfYiDO?J16|HYoD`CapYh+ zG^Z$_;<%_WE6A<5BJjj#aaI`wlZ@aHJ%%!PHS#&e4z?FJ$I!%5bgM%VI8~7PsTdjWj@3F!Hx(n53U>jX57Rxn4Eyp;Wv@+2Qqs-4 z-+tfc=u7f}fO-%ylb)av&ryu$wOfFwBx64*>IY5+I`qyzrDcf;DS}A^fO`;l^!MZG z+;qQYSjt9!g!L!%JvwKnG+NJVb?pBDBSiFS>Fsvcr=L^jkBsjy*Yw2l-bh|AB!mR}!7)L#MxfB# z#Jgl977|D{v7S)5B^0*CZevnFBpg*&Tdn^9YrUQj3i%e%B&y}Z<&DP8#E6_YDBE$@ zCpi`6RZXX*)3a{zab4SK>1*uueL5b^7PNOs>XNjhC$*GSnw9m|FO@A{QiStEZ*y_1 z6fPmPw@shM($4W)pw2fjCQO9{bkAz}+u~%g-uS%S#!-a&O^KCMh4Q6YZuf)e`$)?5 z>74P8qT-z)(%O5m6Zv;CKbCfuW`lIrs8IKkXyQ;XNhdhS&3xzaATaS+X>3iL*BWiC zv)hE)ts}`fGeiKvNf5>X=vp@JroLl4r)&ywTh^r}ns-i4qI&JUm9%ej>GHal#i+Hc zDNZVU$*D#v4Mi>WZOOHDdnauf#Cc&+fLGWP3dgHt5uW`{dBEU$^IvKF7L3L4^FozK zR=AQx3NgGSC(8MTFfykBSR7{{@n0H*3=6P*p%`u_Xnm`NUEBge7{DN(y^oupvc3y3 zJ^=9P3>cGoIX@(FdDxSuA1Tfc7(92ckf#^THtx33Y}0mET~}K@E|c9{`W#J2$y19; z-09xeY4W`<(%WgeK4tl2BDlaCe|gn-$pEfSefRcT zg+#tJ*_<@`WA)FL!p_)}lb^`s_vfJSPmEEO*W=njC&s=j$j;_%+Gm9c05?342;*?a z7_XqeWklI?<7gO_#m1J>Gd50Sv$l0TNe2uU)DeTvPod2@f7OgDPhMSCo4id#?b~JD zc0WGK;@=a`%NJ4UzL2Qao^Sf^iThT@7V+7S%RD|AP`s}zJ*M7s@~OZ$Lr{Lt zaQWJ|i0!bl2k?w>$Ouw7*YtJ-j9`J~^W2ZuL-wtKrMy`1&I0&k?M#8NHL+0N-9SJ& z^#dolgZ67f7mIvUnO8;dy`*9Bk+|yiPT-ap!h}KCl1c4eJ!YQbl^ ze|KpM1yhWk1bmg?bz(WM82G^z&BueHw~2h&^&g5_WJ+*$r=Q`yarxPhM!>*lg#<9= zK_45DG_$M(m;C(YexAm&TKDUr`Zo~8yo(&SUdjr~zqg{>Z_C|ZuR^cvCPXvpIZ-n5FaU0Yb$*_Bj^YTktsdSvk%Um%TNs}ptDBdVU5Gn~ z5xQ}ZG1tC-G=E@w6n~2U02nmmBD{~_xgl_pB#fpVR>+;^BHWTn#kk}TFfSnE^oz$f zu*P(F0>rsXLmLhrIhJOKf=|p#Yz2wWTx8eGanB_9tC7EZlMOWdrAAj;-QPyMx4HCO z4LQq(VBBosR}~vQEYy=-uB|0!=dt;-@#sC>zKr3XJ0s#Rinr2RHqfTv>a!S|cu?3~ z#3HE~Vx)tL`=9m+kw4){MuR)o$37+8Ng4U{&kqF{#y(sefHFBG@@vnu?*sfh@kN%Q zZ{zjXZl$sDr;9DLogYDkq@MCC-AYk<9NK49EfSVgTLp2>`EXM;^e627;2Xb&+77Ry z$>Hd{JEdwqHr9223F!jj@_U&4JAbEWme!K$X8fC|Z{)eLzIo!C1~KIjptAwf#CV!B z;XFPW%_^{+IYu&RN}`PGCCHrI=NQIUZ9zpg^=&k9=#s%w#Iz6#cFOt#m45Ag%rq;|h%)NJLpx`Rj5u{3KUOpg@NT*oYvEyO|} zmi{FE$iE6aFLpc)4W6y=!&-_*)M4=&TsE=c>)R`Z6WVJ;YJ%faYZg}x1h#s;u~}8^ z8JIzu@Q>O*<422p5Bo#-#{U3b@b;}A!Tm$T1H&U&xwDzxKM+N2ZF1Lob>UJ)gU2GZ zt(8xeWCm?@g~1wd{=Fz$8qpy;w{bBm20X&<(IYaZ;JI8 zh%;&0fD3JJb8zm;W^B6LEP;Qxa$F5OcMIj1ye$e+t4l1vEKVMAi+<9M28};&Mr}rL zjaM60TBynUPFuNie==rR`j{Rg#$oX|iqNA|9gFr=Y0jd8_SmV*mZUD>IYB$Z_Hv7H zx>3{Md;b90hsOGa&Bl|bUfTHP%UkiDm8|GGW|@1Y*jw4br@V&t;==P!vWHT$D(ts$ z+3L62oM{|QZU>fF8-6zZmHs5(_{Tu=JU?L`rJ>#}_JOGA(%%cODkzpMM@G~jH?rw> zDLYANJ;AiGw0Dvi-X@8Kz@Em3apGSE_@7nq?xSz0=vtPa3ff)htdrYFmrzX{7bzqd zUE|90LQ4Q>=ZA1caQHrtCa*TL3SMa1*0*4~Q!TB{u7R!J>93|-5@r&|V{bebvD`Cq z9aHUiX9x!8&&uNS3}p!<=u}lHIl>Q~3N+y;`zh0$RXBUxs!??uUp3b^w0``)f>bco zA!>E0xYdkmO>)V)lV0>{LQYd^3AH5z+l{^6M3fgR;vd-S#y%d_8{&tKd>J*4i{h;$ zcxEkOEneC~c{&?=m~|_qU6WhR?qRbt#?uHyXtx^`NckJ$_rsqTcz0BT$9jBPygK!r zy{(w@MrBqJN|v?(mSQum_n(hnt?;%KjL_T4n1-erj{Oqg4U-Z0^if#f>n<(=iOsVpJ2 zeJ;)|UtF+fNCt8loq+(6=T9-r9b7Eo8P%mq3WLMf zJh>z)Z71J*SA>sTILDeNA`Xl|pwFf5mPZM>r3!yrqPlXNX^&u$|~ z;b?@@33`1G!2bXhHLo6Ou^Iztns{s}7|EP?oy4 zSRuBS-7a<{Ku%&VI9mOD)b-m7i^Y+&iwiq=ZJ~w>NZ^EA%8WL%33i5@`K9J?%)&Vx z*x(%3t;Cb7m2+enMjMiZC{n3bbDup-Mj^_y<65I?HmwC(tS;?I!cUT#oTn$|We%P` zPd3KZa;WQ7P>dtX3UuvG4xN&dlpCiOlC-ZIN=_;^fP^2u>;Bo=oLZ1#+=)pi~ou<$R0yk~a= zi{cL!Tlia05?aj~M;3wM=`Jm=u7Qr+$0XN=d#I)#Xn7SUjlRzuC~lH}ygY00>%#sh zveWKAu(a!qPe{AC@ehYJ4MN^Ij+3e#I`YnYm@YO**6%Ha<>jQ4BP+=q?+7fim2Zug z;CGDl>yL@^17RGVD)6?aZ|B>sye)r!8pPH&D=rd7wvsufwV5R%MtH5viL^v((7sY%O{6fYWasmphWi-k8DarTa1j$al&8f*SBx%h3T_(a31 z=w2e#{9CSgV_DVpxX!Ds$tIZ|vEr#U3GN|rYZi~J+-i1kt1H_iHi>I%4ZXZk#-BM_ z__h|CO~19cNmAN)ZdJa_=^%tQ;^3JW2?D9wyH4i{yz&p~f5zX1T8DJ4g7oI`E3&0 zK+x}Qtya$NHL}z++1lVj@!ZO(40jA?AfSzwHGegj1PmBg?z|0|<8%D49^nJe^9Iicz6jrA1CL_LXW%3Q%e>{Hu!a7%ZnBft_hn!Oo?o zqgHUGN(!67!kj3>k}43VCs{_EYFgA`2Pil;{$Y<>@y>@oiY~N25MSF{c%D}})K=CO z@|{A*be>XONiDp;WC)W;q{1R*406W+j-~^zH-jMXG1*{3;gN<-&R?no|TShk`y@Yy%cIzTWuO|Nh zFDQtk}R*5<H|YD%sNIKqmT zw3DSJD5z6>sudV}KWQ9(Ez*qg#KNx&Z;9E=Yfqo&m@Rf&!64zPqR)u}4OJk-TcgEUv2D=HT}d8SwNE9+(irhP4Pcaytn<5{{Uv+4#{_S2A_GW{6z5$ z)|I%ewAaafrdUUREv>;zDK4Xq*u!smFeM|DJaYsDkIgb~?FsQk3F75SwJc6+kH+9D zbAIlY0vH_M6-(JD(WNN5YNZ6})^d{9o@!UOy`5I3vY%w9R!)u|FQHaEvUMd>>o^(? zGUk72!fA4Hr)$TW_m|81?DvDgdWzgKOA=jK%?!~rV$GlzA!3f(%8de~QK}$K#0F9& z4=0%`+SKO@U>wL7_bM4U4EuoEcO3l4aCYE@=mu~{7kMtTsr)_E^wXw|6{6MQ@~q;V zT*hqYyWTHlzYPvFp=Db5k)l|^LK zw@syFeu;t3@Hs{c5mz6HrGuqfz9JZBQ7A@rIpn5cfF?Y^}sp= zQ!By_Zc)w)ZdH|z*1-cTSaLxtw~TH%x!~K20JA_$ze|br&5ws`$RP`pwmAj789TRd z4^y0-*#O{Ts;7Wwv$RNG#U2*6fn;+c#i-nQZRYg-+u|TYBM_hwAuYQl1|x&v{+uIo z7mqFNPU6>7*h2!xHOscxT(Lz~bQ>a!l3U~hsKEAV_;H?MRdrf~aE_x+F0ARzTbrHT zQ>!a>)vI-TqM_ms4^jH7hB`IM1e3S`4g&+x-D)~?{xIquLKj50#4J<8eW+^YM#58T=;!q6xP?t_Ptv}u`KaHe9}0YeK{0|f;Rw9HLAId zWM^nZYRaqSdS`|_Q{iT}*5t6%G-eVk7T50z7|e_h?k=N}IU|uJ#>QEZ<7UBC3>Ami zQ)&9UNLN(5xVyBH-ecrVZwxll?%Y;Y5vW(lBOCf22SHzA_(Q>-8rQWi1$bHXOFMl( z#v1Q}yeX|o1+;dTZ>IR4UefeUP}|+ci8NP@V|{S3T%)Y^vog;cq_L|Hpv$=P8IWOc zcnry7F;%efgehX2og7SPMM7|uS6xD^ml2uf7z)@- z4GNK|TBaTpmLm%)(sfkhMl@vUs7h4l?PDpZMsk}_gS;d8_u({~TeKH)-fC8Qjl7Jv z(TiO?S~Suq*)6LJ6;g#pL|a*-V%wdS(O0;a!_(er*A_Brrg-inG3=flJTgeY{J^E6 zG;FMLN)#n=&T(JUR6+c6NKv?EFzJJ4amkE@&1T5U4OwJ zKWz&r?WWWG1EXpya{}E1XXF0>2kl5?{owOf^IncmF{2@emZasdaKP7}Yv1rq58CrX zj#GQ^H^o;`+wOTznW<=cxWEKvICR}c>S;kI07Q;hU;)~?mm6@kNyeTZiL#pVmWfi# za5Ww7m7n`XCkZy~X>zvpwXW9m_-`~&l}Y9Gprg8+B?qLQ%JOgFYu!%GS?+#fd@r^M z@ekqfW{L?d{99urFDFMqxg>yru!81AF%ANd=V{zcew_Z?Hu4|YC-!7}SMnye_`~te z+9_LkiCSNao-~XkfVb}>Ab~7rf(Ziv*NY$7FXLx~{6(POYd-@%D_ET~U9h^Gr^Bxm zTt~7Q#^5e(G?}g3sD0!K2ms{uHTCc9ZSdz@@jvXh@Grx*dVas8>N;=4{{V{m)$DqX zi>PUr7B*Mk5WGvNBy75kwYu9+ac??=4Y7{pk$7Oo=da-9DFvtbmJ zs6oxSLSF4S)OL>XNyE34PLv(YXs zCB3w`jtj=PlQGz%g2BpVT1i<$DyHQC$0kNkA5UBS2l4EGXt;|`(=^D5jl{Qiw$i@9 zjKWDBCXtw6ZfDD9?;n>YypzQq3Y$TD`;+1y54^BM*BX=PlO)%-NF7maY$CP{+J>jU zcFS$D>_v7VOAP+Q4F3QNTBG{DA=HbDRoy1sl{%A*qa|q4mHD|;-zsdyp|PvTQ^vhUMs0WMkFaBa32kR7vA{eT(P&*H7^h~oD)T;YZjMwdWMlN*k+s0 zvD0q8)eW?%adTqONpcgB1j1PJ8zUb}_|@X8d%2Uqx+KCq7eSsj);`VhTIyPbzC4Q% zQxVT^r_2PisN9Qp4ZMSu+`c~&XBZboHQ@yuO*p73v8j1D$`6u->B%Ycw&g!)q@f$j zNlMS{cn^p3{Kqhw0d@z5nnDsr#ZR2W@)Zw$S)e(L;{EjZUz?; zy~3TuKGae+mdvUbA#uqHN6Ytf(~JtfBr?EIXNPWB1sr2LNXAL&j;semjMi*Ti`ZA@ z23wnSWePwW%wrr3@D6g^0mg7E@|o0~dh?xG^G>Ai&Fd)guPDV?MQoB?TW9trA1}jY zSxp=k29#*wFjzTLr3I@>jT*etld^KDIdj#iQR`BrNy+p}@2}bhQ){IB5r{iQI(Q3N z)e(m8kljUU;mFBQOAyD5@IlDPKRU&%YRm8=!IwYU4fgF%;#JzscO|ZwBgtzRMG<*3 z*-2^!as8y^Bn`yVQJBtf2CNeIE-OB(td zt*3^aML8%`ubEFyspgodsc&r*6j!_F&ANZc7>mVIi;P^OEG6XHZ{5L4O4u#1fVbZxVhgR*7IPF zJ;h{YKPz}<`r7y4N5z}#eJe@Pk^U!ZFfwTN$!it+!K+CFUR*~Uaio{m41~`i1j{Dp z+{Lnf!~Xz+W?Bos+UMY-3^>#0@rCgq5UNw*=Zh`(HgF2=xC_QtaSe_$UmM5u6ml%y zq-`Z09?d>3WgmM7n87|>9*$}2qm&bAtsm^X1qnxmc!9oZQvT4ZX+go%v~YQ3921mf z7a7J}ld`&nNvJr>mT-5)JCUh=-2VU_^%j+`CS}*dNab4*i0pz4C{$1|!)Q=W(~?Nt zU!FcE(=281myP9@#J(3>cJUNhZA(#G2w<6YQ*^fT%Q(1L<&szZ$OGpLn?j5V`_IJ} zBL4vP!2O}G!x!>jSX?0@7|S3}kg565`CGq;hFJg^2S1)ZHPWTjJ|B3#3vGYHa6QM0 z?WNzS>sDG!AloIa$&2k8rNyjCBfeTRk%r}DU^cKP>GFDh%Om0X5Q>*3O_i(4P*!ou zvimJ$v~8s;LvD~wU-B2rEOsuW=O`zNsMCyGzC3<8w(SP=Ni}AZwc3(aJ&WT^aam|z z2=w?wOf38xF;{{7$QVX!(0LMq1d+b{tg4|{V+sMqeE$F{??(*8D@F?@2Lus;oNfb? zllXgAzI<-CHmBj`i?nWSJPL`rCi4`Pmrevk;F#o$k(DaNSPjF0n(%-yu5eBwAm?ig z5K68&RVA_kI3$kvtg)$mZn|#vX*S)y#CluLf09S^Hvm(pxK|@u-gIkJ+xhXBw%gZz z`s;ns_D6&4-2Tlr5!>0DrjuIKB{qv1O4kZJPkc!$E>MPEaKMaY5Wr%%pM;tn^@onW zJ6>IB7g}Uv;VM~M+|2_+6!J#at1Nc1qX5o;oyIV%okkb}I$cJ=Pwc6o*)65T^IYD= zbL3lE+}_SwO?GRxZzA3~B`Xt2o!bBeWRN+oSK&S7)t`tzX?x3y%}UxWH^J6$TZ@^l z;D=9XC$@;qWV4ix-d)U~O$OH9SDcYv{T(3SqVBM8T+MHKZKb8QQN8Z&+FD;<=bYo3 zrfHni=8EUe@%MdQ^BL28yXlm$v`)p^Zq})mHc<(3;P?Uw!OCTezP^5+(ksTx7J#% z!du)Z+EdK8nl+Lmi~^&0ah&%b4E$5AUVMJ|Md8EZjYj_fPCpCveRBIvxYcI5i%^*B zcM!pQaU7F7O)LouMzb(r0ol9d!1G@gN+j_gi&(12Ch=#9++!zkeRlkDp4{@?2<1+2 zE6&V4+E@n(Nk4jNx9@bbO*XESZ}B#p?VYx;9dOpxV55u>~^PT!7GIiEUjOW{9Tu z^OWby#eEC#gT}|f{wWssZdXF_M3(wir@I?%Z-7#Cn8hI|fJ4U@?DM zprv%`!`+uh8CzWyzlj$Xx?c9w{L77aYFsm%*22aTj$Mpz7ne?VaCm9XPuWUuS5pa9 zPYo?~ilr$h&ad!fHjE=lWLw0I{LPOGTc}wW83auila0hM9E=R`F@>zj+2r4B(rXQ9 z%66~XqEwL-hY0AfEA0${TWhHRl7#>u?oFfGD_%6y+pMt29w4{ENMwA1vPkPI2OD;i zB9iJxM?q2F>9&#GZjxO(+GwFf`#jK-42VYE@jFIga^bg!3`4L|tj7Yn*D}$oEfaTJ z>vY?3yRy1hyVYv!pU2dSzcOv;+O^wzYaJY|8{NCRZqmKZTJ8p(*h^@#S%?WnN$+Hl z5s5$&L6vYY8R1~#JLCj0=9rd7&EdXzEG{G57i!(yF^${<`{j;xV4x9@Pf~NavQF)U z8}9zh?+4j@^daEW<(<^9aAn@`w0>F2srib2?B|fRGwCK9{YutbljhsSy3R{|Gz%-3 zhDsR^k{Klf3Z#V!z$@T}rsEkUcXfMc-j2=lSy@_E(d_%&#Yw{HM)uvk6HVIMrtYuJ zWqB^PTD<=NGRi>f5B4-J(KPYDnSXJzMEQ#-YtW)L0ESrufC(ReYYYqfxNj!2d0@0# zh$RZTmYt_Bo(KT#bd<{!!E?A5O~GFqxhAztdW;gwEwtAbzh`0dEv#|5EDFe~lA^TM z?ySLsD4{yq7niLj5|t;Z2thf46%}gh6NO^DtV&fl2*G{ zZpk#P){gdmYR~W*jiq+I3%D^SB@>nuWf6I+0kTF^I8TmfFA%R2JP9%+M_SS`uB>o zO-X0g&t;o9l8_qf<#ry?k9qDJ3Mis#B{MCYx`O zCkGg)w5*S}hlpVdZDn(!$il;wx0WNk%lHsNw0!zh_FEr772)NmwS%c#QOWPmn+S0|1zGu)DE=p#7F(u|W@ zG}BUETBg%ad#7tPEN?&eN6vejElZ+*4go>*f6RyJp6`^;1zR>n{9wih@6 z@N>{qQQN4I3(8f1Cuk#~BoUwDC9**1Mh~qqZ(&ztlW;jWI|+;x>M~A285|RjZZlP` zb-g;!Zk}X9xC-R1TO)B^mlq+`%%hUr0x&VpHPOqiY8s@3%>p~N8D7d|-C?WHeg9G7w+KQTCqAP~Ic1xE*==rf*co4E1*zaz1=oLPqr_f#|X z$lQ4VcEIb;YQL&fsQH?VWo;)m)}B^(`<1VMoUCjqu1;pv)#C+j_SLkX-`8{KnKc`G zH^sz@ZdCluDFbNl%91%5?khI`0ODSOViwtRa>%NefJ z%W+rkp0{6jp@g$4it3zHR@ahJe>I}luB{{1wNHxroz%0zrP%$3G$mGRkfo-Lv9;pz zoz!5d`^>NNa-#!02Bog*y0DQoE4eOXkO0s-6K+&;6U!VG$vMeWp8Ru!^1d;>nLr!> zxX3&nok-yH`tg9@F@PhcNjPJc&!Ifz4xoG1u*1-%tq4Z_TZ(P@w(ocHUWYwQU22Z< zt2-xn#xik)ZLW`!s>n9P}$Hfu0w! z=~KlTo`|tr3(K{&jf7H90A@Cu%80jH$C+9J`4Y((c0=Xvk7+Kr2Ivfdo;c4OgOEFO zjEoV`j&s(mM{&>qOD=MwjDyJ;<0FxfcC7{{Vv4S65mkzmVgJ zpE8`MDM_n2IW> zcAVB8v*HbNSr0qiEVnrYQSK(Sf=#3ygu@-nMZ64d2`0jFRk2)rbC5wO6-dE6U<~vC z{GfL{V;pqFUXJ-dT&4gxAx1Hd2n2V}B=QO4q2n*BQiPnT(x(YEykiKpr+aI!lQ;U^ zY1$Pk&T+bSoTW7FWo>13ewMbESJ4)2^{B0b9aSW^CkU@}8e*(}iDb4n49dqLNmXLJ zvL{M*r3RI)TSg_a)AdVXxHvKSi~#`W1jTZW2S;eO=NN4CuDYF?g0kD0FnBDf-z4$3 zAC3VXk6LWHj*%f*2Ad*JAKiOfm$qgDj4_M>D(9lgB-(OU1Ax7Z-ISy4S5-L0wzkz@ zlKScH*?O1tihpLKr7n&Re(Oy(m6DZ`>CD~sy19pC;rksHcay`jPh$nc;_FJiFFms^ z)3NO?30Jg{8)#(vJfcYV<&cqG9v%^i1T0u7KfG|*}n$!R+Q z@)10!=Wa$xZ!8eRXDkRL;8IEAO*%$z_?IiFz(CSUGMw_oWK*;e>64N(#tyXb{>>=U zq~i@;lU7adWZsE4(?ssoj#{{tR!((msZ_dL&N5Px)m^l`=WbNnP3)cRcc`D)?v3U( z#3kD*eo1)%D+MM<$&V^}s33#KJmuWoY1TJ5nrP&a;a61+DyqjMh;g|Pm61@A6oyT} zDSQ$_4-s3dZHr8>`Eh{lJA#LVTCV%qX|37cl+F{yCkaK$H0QJ?w`wh2zF9YY zlwSU9?c}?H<|l>?O77M+Mgk~icEXY~lG_hFU~U9+$rWB38;f<_XQ{~|@wi>PKRg}C z7FT3t95H7Z#{#f)`yFlCCKk}WqPdRbhud*(!9h~F3>*>5D*|u<1b31|5#Gv#Ub>vA znGPUX001kZ00AQe9syDb74wsonoyj%<7+;7J8h%8l4|>zqi$7JPb4rWCAn+^&JJtG8XHF~DMKXc7)Jj9X`K^! z2LeP%6-wumkWM*L4h?O?s6%X#qM6*wBFFPEl@>y!fp#hwAlkq?6OWV1M9ETw2i8LJ(G`8Pn$YojSE(o%^LXr%t+Eo`t1+Q22%6yQ!}< zi`_=<;_49%+Uj=+bpTcQl1QOp7;A+M#D(Gt00CQRC!^ASKm10syYuyEY;`+82pWC# zPj57mw+lDhZT`@(>?eqpDg45BGoj+VwCZ8O8`pCy1;-~mjITRSIU^wU>@aIR-`Zq& zGSZY^F_aLYM&MHgSE`a2`s1AB)YMelbDkd!QMGL;C`lz0uXsr{W&F0^T@jj2+>ot^ zr@WsvMN?NV<(zq6OE;>wO>gwZkNZ}|rm`lh;7D%8#K{CO==!^xxvnH7Rw$#JPDN*C zWh=f&(LiQt2LSsA$Bi4r9wO0v1L7S!!dkqr#c2drUKY1GyN2IiwSsvymbivhgkEU# zPb%HUrcreq2+&9wim$+MNo#L#hSeiCDdx=^$P}1mjW-EA!U0wi1sE7$4stqIxM)AL zkB{fjo5TA3<^Hjz&7{eq>Q-(}n$KrCy}B-suIZxA`qJ{=0G>t6a~6fbE+lN4@-rNd z`&u@`(S;aBFWRqZS-ClU4m{VV7Y{dHJw586sHNBjvDh=;xG!x4hjz>V@ ze|qOQ+8gEr@u$Ih=Zic7&vW6A6l*pbq<|Bx`LJATO5~69m@n=v<$EicMn%k)BG}vq zkVpuTg(rx$-xTa})FnwH8a9_|)6Kdzcv{}-N!r@X#O{O% zBe`Xy;zdwE?c=P@e=878)8q>qR8Pau2y-&j)7mnsj`)>@~Uqf+ie%gK1$qd%; z>MM6F_gZ@km=ffp$2acRK5Dkh7#mrXsn5z+2LNMm+7|?1bociZ?qnMrF>{=PcLEMb zIqBON7{}?F`V2NlgTggdE~RS9H;rn~noyKfmo+F`lAQIFRN|b}XC$Q*-TZmyIJ`$S zCgVnopS?zv)MT!lV^U7?oKw|CR*P|qacwJlpM>R#T{aX9Jhnu8JY#H%2vsC3s`)LJ;FWA(59V$-rxnGS z;_9)rADZT)g?9eF^ZI*%+gvA-O?|8y=IF2OaayGj&%F0TrkzWqCQvCg=xVdurC3?XKI~roLvl1z!!oAP_*w=cpha z51|?3w>2^_!9Lj^OyeAMKZmC{0QV~p1}w~p8C1=I@?GK7j`S0?EWOtU1JD6x=y&6o`n zGcFha#>L&-Q6Q3eWsVZq4xcM5rz*DKE;mJhS&@n5$tMFfTz#PxWI}H3FH2yZp{!XL ztb#F&EDQ!S*QhOk0Pyh(nX5LrWSix2YR^qp=|1ai_U1l^4es9RKJv6%y0hK#O4jB} zR-~QQ%bwTKTM)4_yv6OB?ir%ozw*`GND;_9h|n^O3?4I%1$_PSLE2vys-*JVJ+_@~ zZ!63IVIY!no>3VO7+Dom6EF&OE` z&mR(Q(tj1mQFa@9OL$06l$is{{EU)Y1RUh>M{J7mbErq^IxltBr>efX$?1JLV((|G zeOMI>!2RH0K61ch6P}6~bm~Vn z_3yzJ3*a3jhGV|xP}mBSjNFpTjtE?2A53&L@!)mLGCS>707~GJ;IS-s4D$O}V1P5g z>}&0xfl)^ zNm6g!PR(7r>7%k*ef=$`&A*#IFd~g==^F~k<6UsX;1MnxOz`+*Q}DpJ4sTg!=8J5O#m2d%3k&-LXz6f|g_!GpQJk#L1pH$Mk{W0vdnV=9`-pFlj zs0%a}a~UAsa@(R{#fT*L=2)69hp6Gy)2mG>N;hq!@e_9P($ag`JG*uHEVmC< zJVouT%L!tpqTQ_~snl0m-K*Vt?RRVP-?Zn4wOvL5;O`IG+zq+FnAqJcIUtSAv08aR3TcdmJPg-c@Rz~<8S(X=ziZ-s zDC_X(UNqCMwEIso;9Hx<@cyrC9_1}9Zr0^i+G&|#o_#(xkShy-%BcJXkus*8s>_hg z9qzPaWePudh2xEY0~rd5k&+KN=Dk1Qr-?jO@VCPLG1h!Lphc|P`2PUJ7HMmJsNIWu zEh=3y&hFLrTSAE~(U`fBfw)yyQ4ZWbYvu7+s`v_DS;9g!F;J;ZP=xAx7`e(bgrw@- za;QRXqe|_@E-}>oA~;$Zj9wDF-8?-=e)e#Jn`$*9B$OMpoZUMozK!c^FM05X!DR5y zk8Zqsr%9&xd&B<#@P%CXQa=k>=@Dt$E-rOlKTusr|SMP@rBNfs(9PP z4>a0VwGHN%qUc6#FG*W~mk>iG^2amXY93TG+>f)|T|JYzS8HPNBQLRdlNUFZMGpI6 z6}&9O5hJ=>$q@vPl;Kox6b$5%l566zwXyij%MXjpYSWe{*|;@_T(qGIYDy4Q8s@Do zS-Z~4?#VaHbLnsxJQfE9EH+%~OAQ(G-m84lob0712W1r8Bks1+-rWv!;T_(w;Y*($ zM`5O0TurQaFpK+=cirYoeFK?$V;U@AShs!GyX5)6yew*;^q&Iia z{{U`kGiy4Ou{Fq*WBVi zwm_{DHZ!zm9Gu`D<2CM@9O?G!HrSCHduXFz8NYmX;HmkJ)bj9``^j2iMYPiZAu zPOR@JO}80c=?Ey=QoB)6NjTHxPgyqP+dV8lB&o?plwi`bnzENQ>TdMcnWmnpSw-C| zKV$L|NE*_~1d`pGa??t~Az~snIpi#A6O0yP%8y#pduw&) zsXa5#7{y`P9ik}_vcLi`-@;^XlnzNyat3mJPDv+9N8IuOjQN)8F~|J0Lg43|k&*43 z``5(ansS}q(rdDJcD}ncvhzIJ(3+cqsVPD{@^|>9Hz-E(ZEMR2B^bw+I!W5?AI?YZ z>U>dm@dHxS97`X8ZM<=!+I@|$Z7ywF#0hJxneIirbA7rgrL=feqiZ7!N~!*q%`r&! z{{UsB_<`VUY~6V0T=1Qb!K=HQZxHxDQn>LHtKy#v+(#xZR^LsNO%WxE-$OOZ#rDTA zJd#Nmn<63QU$vKpH3s;f@f*cg9wV}!PH&2)(%-}Bd}O|jrLeOta`s#Q0CnX3oFg58 zptuB_y=*`1r>cBv@Liss4?{QoC@(S8-}-O}d=T*|*BtUh>&`--|WdpBnguyg_~O4@B{I zh*sVyHJi;gOY6Nw8Vh+1pPhdmn-z(YQWi9~mRMisG8S!w7%UpcLb*0jq!yps>u0R% z7gjr%e`qnD+8J-+mE)1JkzuYQP$hh)lAcI;ct3(ZGX0*vWlay_*TYX2YX{;6yW>0f zY`jYbwtulTKMURH*Jx5LF2dbo)U@qZ-e|(!O>=v7Z0IJ4TX|9uUqER800Mk}F_e922kX56C~H=dS-XPcRJdae7=F2Z+U5{@4vHefq!T1Z^1ezkNz6? z8p}zSUDJNUtV3fnwD#9YD$jXiIF-8b4)4W#*_0O5f2Pl#F$rQ!W@EmKKr#j)2O z&fdn&ic4*#>Tp}bXf5F(vmAGRQcBzY{lu~y07gGHzhb`>c>6?y$NC3_*`&0!v+%Y0 z%Iea`rAc`D%Fl9am6y*mM{gJj3&Q^ZA!!;w6ffMqF`MI_lE&j(*6+u|%bhaQRJhlN zgJ89|&~GjwTcy0X)ULkUWBrvJGD9`3+E_<$r*b^*$+-Qtc~1vAm2kL-xnf*ZN;TCN zI*-}4C@*ZF+jf$Rr77LTx5}*(g1r57r75`P5&dg|dJl2aorGOpYhr;koH>$$_hWlPPW#?3Y+eHeo64M~={Zv6gxr*8%}q*GWe!OuqbD}Gn@veJnwFAZ z&S%DNhJO)s9};T6+t$~&ns%Wz?yC#w@m^ae*|hnz%S~d(PKNfq>Q)oQZZ0Ob zxqI>c)Lvl;PZHs!j{%HcK$N)AB8+4t7-D-)7@!5VAQNM-CI*>JYV5!t7p2p z`#z(lNiFQxrrulaI^pDPLr%GPZexi*b8hT>G2%!ewbZoub(=eh$hS>aC~oepr#nQl zKqQDyZ5Z<7S7_u|iIh?zXNp;(@+Dd4d0*`} zj))8rI1A;Nq1a=L3i>QpiFvfJ)FbsY@e~z4Y)9556;V@xbwBtsqlvO7}GIY6{nn|fsrzm??uAMDhV$-Lqm*R)SKMeS*N74TP zXTJ)+hbE2f;?lfbHYu8%oNQ>bE5+ zx|JQe3K)ao!f5SW_F#XUoQ;%Olh}h^bG4ZY)MaVRvo7$r#64;bpqci{c$V$|*!pTi)Enx2>7QvOKSD z%vDfEpJovg8Yowje2cU=QQl~>q*^YVlR~K>(=E#&E%N^C6;Qb(uo)!vDh~p`K=AfA z$L6nQ@Hui;m%Nj$QCm)1S;Lmf)=Jx2{(l(NUsb|JEh}a?`NKzUSB9hBQ+Jb-m79~i z-mdP{?X5JqWxIIdxAG0b>{cbVv|;m)myDM@W2rTC!KXxpN?L?35Ft>oS6AH=5CZ(c zu)y>uuN6a2lG+5As0<{ye17bonSSuvPZ-|3^PG+{1zeG#WelpvbkM5+i;RXFLHT}c za54bkbDR@js!E!1x4p}2E6Lx_RQ$L756vYhIkzp`uJl@U+S}i2C1ZcXA{g~lHtmg& zyJcf4p>m@tNCmd!9i#*NS>p%Fnn_yf^fP2N-Op6oNb{U$A;{^I$LL7Mrucoly-rQb zAdFdDuyAr%qGVw}8%pwX$UO)-uP9F?URP=NZ=QUHah_(CxxgDvG0=029M|OjE3~kj zKTRh80Dq5@vTy!f(2d^jXZ>~kSHj(EXRWlaO9k&}z11q$T{^V)>9;})qjMyzvfMn8 zq$V^C$W%lq{{X^GHLrYe@Q&U^^CG$UgYfRoXxMPpw_YsKt?pNX z3Yj61z+r|%mK=d!2ijXlb8t*SnPkd>&deB|20=S<&|m?_Ty;OCzXo*7d`I{>8b(7$ z@fYFikaLmb_@_vdX*ukO-A*z(8vF-2#ZG*(t5$QGr&9Brr8%Wem7{kzDOwSPQoHwK z9TMe9e%q8&r$-Ntl{i8XbYzrZqX_eIVrR5eQoDC=t9QNIZ*$_$!#xVq#@`wA4Ho|Z zSkg3|H^#cW))8q}@-6gMv0K|aSzX=El9}L|>i*_pxFvSR0}X<|roY(KTxnmkSHZ12 z?RPUrY2XbGC|>ErlgSJ^WE&c3HjVQY8IkY-e4GGCugnjKKd~LorQ<(|TJDwc8rEd- zX1#Z)M{j+k;cX4vcH&EQxrXW#ks~lTR&-`&1xseXUj7F7KzIw`7l8aVKA?3;w0{gi zX7}PHhB-W|P>NC|`;n@Ekt-K)fkU%CSooN%Y;l-OEPb^qwJFs0l8S4e-@`?@wd~<5 zNjo>qDBW2lyZp-=f~khX&Q<8jF~rK8X*pU-Qd6rot$A|FF_qoor>eWXk79!1jJJT1 zfqQZZ+J0cMO6UnZa8zfEb^KFRSYFAz$hW97Ga!(lC2f`YV5b?}z>p6IJ$S6NzKhPe z0Du^=^1!q(>`1KZ!XUqBzK>QOC|=V?`Ig5dBO7Q`_*^}quIrgPNSojPg1gHC0l zz5Xcq`RVu`Goevdrzpm8(h|CDHT$UReHW+Qp=!qB2<4qr9bQ9-IW_$HV7h4`*ygxVr5^oOa4!rUM zSX-T(f-sjphtG4Wr0XRL6pzVRjxvomoqN`NpQi}JIU2f#`zP%Rj zTi>nDj6NQB=j5u~skusA(wDvME9+@$FxAotrQ=Pf+hlC`J(ew`v6?9<1^m`mI2LTHG zocy732pvH=<*Vj@i=VSk>~{`}u6#!Lr|^s6!fAdS(eL#wV_vw^W3-kyLMuO%R#;(c ztAYeJ$%ST?Km!b%eP-~&_Rj3&FjKb}83h~EFc|7c{W1-IKVR@tU)rYM$GXMe!7mEm zpZHfk1-VP#9_rTehL6RbDMSL>!-xSfPo`*4FrMKs>v?&pAYhHB4c|q<8E+8rCVxvW zz-GCg29!U2ndTU5b~6w4Oa(hSwOvYhs($>SohlG=T-B#{cvGm>c*)bFg_PVSh?1Wr z96P5O%C&jg6sgmTQs$KA;G(%?qT7|P6pzT?i#{^&ev_(ryHxl^;F}MIejV|Kzo`!a z_)|}j?j+H?I%a6Cb=^`+j7)VsLeW!IyR^WH#`@xIA_?wcw2tK(>T7MYW7a%eA#&+mD*at1Zi9Gu+85 zf}wyOL8~BFnVf_>$3j5>hAVe^^f+97Cf*gzHNOgQW~M9#!hpuU@Qa zMx8Z?#8s;~RIOUGrsqNN`GjI%1{-$vVo4a@Z~$z8OBBf% z1mggXbIxk6{{Umu(LpWtE1*|^4qzyu0)PW>3bD^8Es?;e&VJGkI=*;4Z_Dn^Eh#VM zZELoT_deQKT2*OPqc$92PQU4W)R12`Ex@P0OtqIPYn4(Ql&yVpN2IB(%$!)J`B#yQV+ zTb$xB*?tBK4?;?<2;wB|HECjM*ThXH7S}9gQt?~=05fdPk0_NvWkLcNoRD6X{0Sr$r@~El!@dmE^!tl# zOT@72QrkzU$9r=n&Y`IbtLu+1WHJbzStNbC50s=5>?`VT_$8*q{i!@HJA!|*{1fpL zQ{WOqLE#Nv1yDe2A2MZNcJf95EJB~mRgT?lorF*$EC3fs(HL%AaKS^Iuc1%V3trrNGS;IJU>ub1QOZ1J2soz22D)Uu3C z9$2@llwk(dlC|Akto+`m+~wReM}>G_Ho?OeTN}?h*r!^(I8&TmSAwFU%L&dhQB;$= zmEGF5hmP55QeXbif3zN}9CFY0i-{nOofs*W^5a#HWUY)L-4Gj3&a0OyK?1%}@vp%j ziQ1oowQUN^!@6DGqkFH(s3b6I(6arH`!?3zIRulz4qV*BA_O2EpfNn+yAK}to5VUV z#E%}`_@Q=sFqG{j2Dt6zuK1S(sG+Kkqk)N_x!lZw)oNU7SdGz z0Ez9D*@UCA-)Q=I4l*ReJ*~a7joJPeT>97EQpI3s(ZXS?#=4#x2ZE(|E5rT60kTq3 zS}4WcC!^`N^WcUnJV;oi!45{K3DaNHGQC6=zLZVSqR;d{|D8~0{+B^M&;>(F_e`cQo#|6#J zy~WkWn&~aG80BS_c& zhI=+-GtV2&xpO3H;xO1jo|env$HA#>H9J`$eJJS(_wFNjn_Rtg zIKjXQ$_URG+nnaU$j~qT0@`@Fd{LlkeihUFR5Uw{4lP-)wJ2tfNtq^@G~*T4qdlpO zXC_2r0iS%1t0>)y__tEWn|_TWNIuXL8TXD%X=4Vx6 zo)R#r8K}Z-^2tkErFN5cx_VyD$?0SCp9nI{WhrqLOl}7mgM6877)KR_#9?J88RF+s z-rkKBK3Q_zQ|IJODO&1Hs1Uf0XT);{PQ{`C9#OXsoZxM4s!s8exIcA#An}F2jQl74 zm8to6TAq^|XxiK~45s~qt7l%(xWqfw~diaPs~^W=8FlWFLczQ4q75|0va{NqBKmSvXvOmqfkjHescC zlpCErTl+Tma836Xvdp1lU`L;7QAsYI9GyZNn>n^k6D$QpdD?|r%q+2q3Inxd&PO90 zevABT@Dccf;G?Q(3Uv*0!?vee&_$yaI=+!{ZnrY&@VsP5(p}iGme-aEc{cT3*#q;x zRf%G@ia636xb9-yFQU|L8*RIM>XJj|6C)u(nHm1_jE;EwS0>|j{n;e+xAmj5*{yE% zvHXF{9&1HfaB4DBjFWO#x>vQEjpE~@yjs1~lBXrivf4#zQuZ+k-cI{um`5ssBE>4X zFBW50P-6_FxFZK~u0)qMx3i_p$Lvu7-lg&=M#G;60? zd5G2*Z0f9rPqa){JT6-)Iy$f$!$-dWZESqpSh%>-+(!17`cg|AaZPJ0S<8VFs<)GK z8Jw8{Ibu^G#CSW&AkgYQTRB}TE>`X2z2^0`{W@r4Drr7t1g_+h)$7&r+Uef*(_3{{ zM;Q#NWl3(Jh;M%=wAalb1+offzDc8tOqMB>$ux02;S9!} zM$RD*yvey`Xx(yhV+e7HZf<6bpq>_cC|{4ZU6VDU#)O1PKoS_n0u|f=$R}|CiEXZT z&F=J)Ppa3J{ZroQue}Gl`4y#od6o6i^-VU^m9){dcXZ0WR=zvPeZtwOKH*K)Kt6|& z(DOw|W7C|M+ZWICaj8#_o1Q;;)1E!3rOW>SPv`#tfiM0*J)-{rpAi25!7u!dYvM1D zH4g@A;tOc5@1XlFq)jqRVG&C-^UW(PUSh|0=0hxT1dvFeLuX&WAReqiI@1mR9=P zOXNc&*H@`=a}q-ovdc79(OcnCCL{nDAON2R*1jd_+F!&U6>DA+i7&K0b5KjGMuI=E zX#y6EypgO^0Xhf|$rB4r$7;8ioQnBqQ0Jpc7<@fQ;v-5GCso_n)pM4xvx-VdT71e$ z#W}~7tF`tq#mX40Ld4=B^;c3*jW?xQPAbuwl5YFBxHvv*si`LxrE(o>#!%~D+1mV; z#@g21=eLsc&1gK>q={A`7!Tw*S0M_h-i5#<2FGdPSUg*-c(YBK2y`#(bic8>)#kI4 zPO>)oM3XvPyG?r5_cLt?Aau0zCXO(NXvoe)v)FjfOHUJNnuVRE-I6R<8cv|BB6+Sp z?CWydJjlZ^bxG~5Eds=WV_TPuMDfZ&b0E*m z%r=~J--ny0Qk-i_vZqUx*Td6``wsGoa(szO(M_c&$v11aq+)6F(WxpP!gXpn#|vJx z<8>EJwKSmPIZB&y<&Kh!qNLrC_kN|Ncq3Uwx3kvtZw_7Cf|_2hr0SMhb?u|G2S!_{ zXNGH=a6t3nXL#mK%IZTft~W^Wp1+~$m);EV#J2j4+;P44hdfzf<=$w%AhC&(DdYas zu=A|r)UC{rGwJtJN2u(P+mx|uYpXktI%tDWG`AP47#9G>izC~K z5P-M@fGg|p`R)_i!mqKdhr-kMTc-)sgqF$@rB0fJ6jsu@l|2_Li)X~w;oNNK&Wv$5 zd`>Q^bBe82of*aHCpgxxQO-`IYVn&^yEraF6pg`Pg#5s5C_pRO&rS)i zvB73pP9-Nt6+%*O+_fr35>CtAahrvjy1ZIVbz3*^`0S%Q!pd>0gs&LKM(EO=NWE2` zw5FnYQ6RQc2)*isd{{ z7OZ0b0ErifEDopTFgiW`?WMd4KB}A(QfrGwLDY9sr{ZA zlE&gm86k#t7ctFl<&c$iSxjomWr%dG=ZK4(u=tWi+iRxGPkITzS6Nx}_Dg zovhbAJUpXLHQ(>KWZ_noc*VP@b3ffqYFwV{QIqAKw~TM0(Rg=K)b8xa)#FP`_1qrZ zERar78w9)(Dgh|vm_iDwhdl=!5;Kw+fx{dE4_>F9tUbm!<2WX=Zu~WM9ojyPqG?xt zLo|*r^((7c;+xB2B({|;E)Wn&Vr1M7Fh@B!y4Inp_)%h;Tk>t}ZUZH)u)d2@)#JJ- zWDZf5$tBZQXO_+i$q|)ZQeISV9At3x+;K8?f=Skr(n)E}H_DT3w7u15b!B}{YM2>f z=B0#!ZltXoJQ~sJ)M>|=%atVbZ9N{lU$pshKsh@}<0IH@@4*Ko6VtCIq}ch$85@Af z%V7I==ZuVd9y5+hL-AIXtLfJBo5*dhZdu@((pGdaTq!DIisj;4d3?kX&V)#;t17D? zU`2HBw2K&B?IcJP2goc?5r7;LBb13%y_$J8V8aQPSym0jqln7wBZ!86L}?l1F@oD!*r~z5cXzkDX0^5Nd+B8QTYYYy zbnZipY}%B$ucgwpn%7(DE4><4Y4=RE%jmHbCN|yOoM#EVa0L{>X zN$HG@*!u7>kFE}L9jg>|nc@7H(2X}Gu^N+@<)s5nuX78opDJ2{3 z+D#|7ShlaC6lp$L+E7VZ+G-PWYjm#}TI$!ck2cM_T=EOW@p`HoZEsCyjaV{GW97#? ze+$YZfDDeCK*E49IW_2>6pTC(-D;~M>SjXMSGG*?#%2dBk+IsoL10w|aLReEI$2k9 z?*%|PZP`{)>Q#paAmC(!*LOATJ{p0V($>&DoX<1>m?UDdPLihpDNxKE2{;2Ja-^IZ z@%VzGr-r1XDvnhuPu+8EB^V}>T)JJ#%_pwb(E2_UqUz%@5}av96sX7EP>nrjQcvEJ zlD{g2_2qF(;z++9-|YC#nR6;5F_B}v1<6)$CT51?FSzY15ZRT^<-(FrA$GAX<aQ%B$8T`P%>?aKzz4gMo_l)`m-H5gNh#wD~`Fq0BpjV<{(;c3~K0SAh)-QNhh3uptSN6FeOd|tPre^ zyB{zhZoxPlR_BNOH>~)U`e?Kp8~f=K$`@^Jk;!dhkGw-A+>In=C6KEsvZRc5x5@&8 zU9z1jROMQ|T2yGkIZmZol<7hXYtD5g2*+I&O3stb6l^46g_VN^Vya4(!S$Ga8%N>j%)UIkx6_tcB3&`lQHi6v z^W%-0cef+$C@thK3mD><1c_!D^E|cM(YzDz=UdS(ylJJ~E~nxBHXYZOcD5HfhP<}M z;yYHjvC`*D7@bz;NSF7QDD4?Clu!t-na1&6M~0&7ePXMn?WxhHils)Q!`H1hE?RV| z*?UIZT|QK)sZDb8>bbrAFAL{bik`_*qYAE!t5n0vy*T1%(u-WxYEt*y6`F0gB^%yJ zJEilzo#nQxucWZ+b{1L)5Q#3e1k|pzc-hOeu=!d{H&*ZR#x}^zVjwtY;=Qw2mqxeJ zblCh2Wj?=qBR|@%Zmn)@+E*c3DC{D5qZ2EZWkhi7Xo?}{yLV|`;+xgTbU?QFE`XrZ^ZYo$^lWS;WQD0Z&tnYXI&;`rMcgji}A zOrIT#o-S1$9mb!rrB%WaoPM!cN^XTDrygHzP6}6QoMj~BZHM4|7AAO_*xc_2hK>$2 z)p$9o^=Z12oNY#$QB|tR(~_UDl}ArUR&ax}`P*Ib7l||tPS-`%G>tmTR=%-aM$*>m z>?nAqc;baaM&!>lvP~NKaBpb$6ChPqBRg2}jnn;(@C1KijNy z__doWG`75nBDE{2T)V@ADni7C)L(>mx0(*A{kskBi?98%IP~~nw;Gk4aN5AlG6xbQ zQpKpvGt7Y>bVlEEf@H*g&I2{iF%+;wSsH6)KQ|mnXmNCfZIBf`ZqbCFM4rKGJVy zOK9~A8>t;wEv}sn)%DwL`H$}4ibn{$uwMWH--2s;S)IUjRtoAqLc0hBN##fkr=~#w zj!#Z&7T@81v2418mi{J(N!6Oz$)_dVifQe9kTiz&&<1vqQUQ*oV~~!UdE?%xo72L=r`Ne@x=uXuQ==G0GL7Lb zY1dMkl1+0$GK!MqUiOc{r5i}A;T>{9`PO_;v4U|L?_1eXQkV28qtsqI_NnibI zfso%a+$?9yQO?mAjTKb<$ABBu59UrT#n8v`E@_OyNzR5N5b9HuqT=oB@bHsyl8avT zIjE-;+-&r{kLo@PpCS1>tNff5e;T8R3UO(n|+J*YO z&||qA`tmX>knuJ3{kMxeAsvRDaepn#-mA$L)V8%oww$}%+&NfdO}S(eILqx3=1qdS z;Ba`xNaLx&$5ZXx;P5>vc(+M29IB$n9@ZcRC*?a&QoIAm^y`klq11|$bxEtm>wVL@ zcTF{_PebykUNhaVc1xxG;5Q+N`s28%7EDH0aUqE( zIl$-q_T%%a@;Cs1dK0vQGJSr7kH@xZAmyWC0|2{#AdDX8fOG6K#Zp#{pP!%kiLX_z zoi^#`=8FbgW01h(80rpt^yoSK58-D|m&}?@dZ{H_7(9W2p8XGegT-O9m5~sRSn#`) zG2o1VPs|2MC3+0!9YyOs!QF#L@{iz_Hz1sHcDdSqQ-Z)}6&7)N+h^O)zS{-Uc2;{P zzU$uCeQ)TG2l(%CEv})WT(dB@mrlHiFm|buH;~EPbS;(#1F*@gjVj98((tl6F^fow z;wB&;DprjaQ@CU(C5Sxmr1Tl9f3zzfC&F?z33S$DDjjpgeqg{E2OIuxLJkjF<8&Lz z7ShUBlYH}7%NsP!8ZpMxnK3IC83ENWGC(DO7(bQgjel-qI=j)oWR)6g@76D^o~P|R zH$V8s@Ji_dtbWjE%l-%eKO88TU%ISc?y8B zTL1xN5^%nBqy%86aSY|MIj^2Pe|XKVMRjuJo_j@TgB%BmW|dX?@CHif19sdFhP^&r zV$Q}m;}>wODCMrPB4%fNq4OCT-)c(Aa25BsQI$-{o=xMp?sfkF5op%>RjXY}_7On> z+G65a51k_f@?$4tjk}cG#Xt;B4hNH(Q}(z?MN67WblhT>GSYmuioe-UcW%8A=;1LG z=vMZVaEu&ZJlx`)(r=l*ZRGT_P5DYr&o;_fWLS*xGoWSyL`}gOPqVgoZo0TWzM6fe2@m%W}#N;(+8=t^5U2d;@a|;o`ILKZq=1b0WETEwu?F zR%ul2n7nF8mM~I7^Dh^+APg9YK0&;$CpxvASyhXZv}w6HyT%dHO(|JQZN9cwJ1a{#1?8ph zkpQ~6hD4s|LW1TvCm$3 z-JYNY9OPFOX@ez!P|b)gLjlg+(g4KrGC5UPrFSJYyqZGTccH)(k_56_<8GkPdQB74#p%E0|^Y zAE>;mgAa(bt)XymCA>^9Q?~=>o4}aG+I~MYEi$MyR%)ck3$C6 zGfzkCYRO-tjJd6?t$XSCZtr(Qh$ZEmPN&XWs8|)jd>L*?Aobea59gi*dv)EStQIlc z{_1J37Uc+h2+?ljV$Zjds-ts&a6!QtuN1eGMdJ8lh~Z+2&DaL{b{4w8+5yQWiOA;y zz0&sLIkecFVe=+f?^7glr_GmRE>3!5?&kzxSIg#U#=a4)6r(1cw!6~J^t<%8L)^=z z<%g`Dw5zSIu9p3Dw%%RVqhV;SbsbNB$c4_KBjaML5F{>+TLT-LZsyNIaD9Dt8*nve zwS;Y!8+&Q(kYFG9_nXXSAo8xk27iYDkT+L|q_M|7xB@VdHBa<+`Fyc#C(8#Rivq|n zFgeL5(EF~7ELS?rB4q*2oV!kbb}q5T7&l}^elmKI+?;qhf^kYsT}G2hJ2mdYi`TB& zb<*o*dN_GGdvz3&ji28srQ1~Ff0{i5MOmb>x1MaIrrzIp3>XIBuqP*g*$3AdIVQRr z}_Uk1!TKO$hFlq7K}k@sK#R0 zB9c^T(TCp%G5Q(%JAT*S4}1ae)4|>jpW)82;=OOfmwLsHsefq>sj3T4w(FXPrEPWn zk*B4@8#J@Mw;p<1A2F5H8JG}0@c4D{C-!1*5%`PYR=uO?nqP@LL*h+FJxfm2v_={i zi8TQQqRn+CsdXD#wd9esQLJ8UM2Po9`78#8z3{u@&%y5;-Q0f8zXd)OYkv-WQw_D$ z^I1tAjjw3hg{`bm&ugj2c@_P>r)7COO*|TfrPMQ8#X8%aK3^bBH}=L=ii6AY>^$)E zil>3XC_1$iDbz~|g^x63m6y7lqML2qru1olHD+|2aoF0N`pXxKw<33o`ptHH5Edu6#_E&^%UF8jY>XX*XJ= z5)z3G{LszzXwRDR#~61UH^RT$v&7#6d_m#=0NJzQ=Yh5Fh1YH3dp!>C!+#L;_FTLzO-&=oaq?Z$E^5vZ-u=8y$=kt8Gl2m+ttz2Jz-ujG4+Ao5>3+WLt0qo@Q#uo zrI~(dV~c zwUz9e(fqz56%_g7%?@k1Nky+{oUb;TwcG6{yVmOL`m4l$u{MX|j|^&lBly7vkK->J zTHR_|hNa_w1!!;JuM*g3tu&VjVW!?`7MfmrsM#c1Z;SpMc*5CiJVC8qMkTSdwAJUayT40j zd7`$|TI<8s_V7%z#4aR?HJ$eV0Bp@CRQP>)sr)|h?~R9vd@b=S!dG@0o{C|zus@(45%NZvoqNJC@ zDXvt%BtK+5O3y~rJa^(9QvU!{T^`ANHEg<7yh0mIMtxolMp$k&8|$AgJAbf4V=CF& zPb_Hbb#!7v!SVWQdGVI_LengDl=0)}UKO*mw2Bxc@bc>RPYu*amiAYSZ0=%~-ezwq z9fkbd{hBStJ&U#b2Yea$EAb%wOz}~4KlmN-ui(##^^Xbo;>Se3@MYA-^TVDwvGD6$=z8s;i9Fjq zO=iB1PYUV~N+nTf@ai^kCzU)JjL#!QADf(1t31M{I+b>)({QO<2{#K$f}t8|)3hhf z)kwKcQA&4q)0H*Zf>>{>tQATwIEmg6#K!kkeWRL`moiE!ouLHon^L}#x!_tJx1;J! zWut4}43}Nj()RZ1#`nVQ;m_@_4&U5JZQ;Dqyblf1>l%KYYHmFHoi;rt8#K2^ONf;Q zDY~!r$AO18Y>HxgjvfB5F+HIv~fowt0_^;+iD*Vbgvx6XQKFn#CHB0wT}11n&zXd=@8po z+MO|l%d~dW#=4%j4a5s7&dCMT?QGJzgUxVX4?IKSKM?A-w;JxPqs64prfQIQi%v;o zgTi)@Lmbx-MFL&PZ#Bj4l{AkOmv=E*39cb%{EKu@)rAj--&53Ln!@Jhd%Z5w2{nt~ z7HSKo*-q}s=QfjRr`zh{=EibNR|td@$d#yl!flZ(UFoE)JT!ksnCJIT&6 zRNdf{m7yzCwc3)p(YbU}blO$uQ>_%--XcxTF;u09>=22ZvX=(`1Qm^yr#c*ay>sNQYlkPkIW#>oRF z;k+^oaT$JJJbqtW&LXAok>q8AvYAw0WPEn}SlxeuquG@^CCn8qp!(uVt zQ^sPc(5X(92-KB4O{Maw+&Pkz`Kr<7Qdg93ufBM<_JR0AD^n0I|N{;q8{OMqTz1!Q{?z)LB+U7{qLe9Q>;s}4W zJ}vwqv}-&2=+jg(C+jr+H_nsv8}V0UR`P$M9mevWu+S<>_$+B3tq zz90`3j)m}#O3^MrMww%j*lAlC79i5Q85UF?Tx`UVxGH6b+u$<1E=z^tig+4T=SAe0 z%CzBHue7N;m2fb_&Xg*`l{Y1JmXK0TO=_CA%wqEj*_Jnl<%yj>c;-}LDMAV~;}~Ln ztR&$n$tzjCWcinCYvSG@_#33p@h{>30D*KL6xcQY0K~gr5!p+u-oxZ*+Ag6F+F`c0 zb)FtzP%Ci)0*qh=X?Dyk8gOJG&jkIatxYM*#=G`Q@vDGik*7nxZX_|^T zx6~q$WqX3KO)G6pjJY^JLHtH-9X>n!6Y({soeqv(;YVOn0$gV?fEVv^CfN@@VZ=l&DNPMM{-bo#tVb0c(+mbWSCpqNu zIVvmPJbB?sv>S&Pwt~xi`?T9%BuPBhu{V})E+j$`A|;U_QmZ=`QzS8}xnDoGwMSxO zBxiO$P6;^Uu*W{97&+wEhr~Q%kK&40Ibv}5Y&0;Et?ZT;+eZG^lbKYNS;@W}Q(r=xsv_#qHKG@lTB zJaE9D^;3Drwm;>ceWP&%5^xW|<5H_ygk`Fntku)fRVmYZ+W!C+&Do^WcD=s84OP&~ z^D50g_LaYLja1q}oT{TIa#P+kn{_tUeuS9wN86cDs@tGsG4e z4y1P7ETRz?iLZ3HRLkZ${rN(Qq&Ct(KW1sa5`H%LE8&ffvE!fF%i=Dbb)tB8#W&i% zkKtWY!k#+R?V|9emo)l%Sn1vo)-|i$V*dcee`ZC|bj>as%jLPbiVMqlWLHu86Mt?P zIF5BexMyoJF$A1|NMYC>pdLR7ERqC8j147%5qmvl~PJK=KNn3#u&QvVK1rSc@*xc{{XaB zl9N}9bt*R`(z=R_5|!o6exD54{B6_Q#AiUh@TbJ<3)`<0YMvgmd+&z6GhH?3vheP= zt(l)xO%1Fe(=KiFsjaOwJByUDyVT~f(%_y;>-$J1`bE4iuV3j#>N`tzER8&Nb4?s~ zGDkInFpc7O1{qwiiQ<$auOXCU1JNbdygO}rmNygI3*X$UsJAkh=66-t(g1e50##0U zJx>+T3z!0sk^tBQub~C72nr5yx2AEE*mLV)cteNhQlqV!OA!cOomzBp5mhMFN!rql zK37sQN%BfAEh#5<*Dn?;h_e+MGLBswE0k2>I<%@z6=_*U@KSKJUaC`E&ACOZYt8e_ zdT)v?wCx}d3|u5udR>Cu#R@C6jL}-euW1Y@Op?a|UnDe0>f3%&Mhz@J8u2Z`N#@Wd zfn;L9%W(t_0m$6(yvWE-cn+ZYjMusg_#;-5?pQ5zDO6uEkC<7AKz9WBm=S<8&vBZs zsA^XBNY@wle`c`?h^1nAOphrFpll4}4aemQc_5MiCb%nbjz#S1R#@zG-L9hQVX5*y zYK>K`dQNm{$_gu%UiUO);N<5UbW-9>!YVXr<+x=zHyF-8T%4+XrwU3HBMOt|n||WA z*_2|VCj5F&2vasRiVL9M!ISa`>t3y-p#pah_w}$3BxE)Cg zXc}2S+w-xFRJp^-nt9DQYNvR>^3vV>g?9SNU`Muj9f_*INTpBs-=O(;&Fjo zKB&6Xf&}oqu~TZ&vH3n-N{pjV z4~VT+q+=M=r-_v33XX0Z)Tz#m8g*l6w^3KA2-AaA9Z23Z->*X(nBrwlRqJ7}u%|hx zMztuYO(^?U?PnUb>d=x+LYt)ulC4tosne+>=O4~5+K=|;_-~^8Kh*pk@H5A{2aSFv zc#G{G9cjEfsoUM31zCiUYTE7W(8xqr*0Dt;rJb@dx=ZV*CwP_!Cze0vi^o^zR@I+Q zvz;W-w2PaUxSl>vt*lQgT-{x^-@K9B%W)xb#J4v$c`fDUrSWF1tXg>U;taMIA7Z_e z#eOQVmj2~phU!ReZ)Jk&M?@;H-Oi4|&gNKyJFeoO9ziFPJ9yArhL#{zyqlDmF8_BQdaV|U_j(~pbd?&_At=k)(WzB?%X)ODQ)ZTn+3)9M+4SG-gDjHx z!7X6SlTG4?tm2PyBRr64clPl|<}pyHUPS@jmNn{5&`9}Z{3+rX@8Qx7oO5coVaN7m zrRAOHk^-Z~^IgL{mN7exs+m?PnuTiw3lJw~#*qcU%q) zbzv43o)-&85~|CS1A~NTPDv$fH792tNnP_v$=cUiXw}cgcxh+UxLXH{$)|w*<~KR5 zh@p(4=I0q>agGiZzOh9{GL;&1`4nX}C+!@aH7Km$B!Vl8cML8qjPT18hvyPovqLfx zq=I9XH&Q`4+w$jwU#5TXOilLR7k(q^s)}1j{hz#LDm&xLj#+$3;ahcL-*B*5*|1J_ zf_obL%$c^m^6XKIi}qz!IFC0o5gcHG%@{l`GW!4|6UBa*f5A13w%#HApe~vrF^Av= zt!h_$LIjsyD)69IX#&ZzG>{^@07%>k8+Q@%{8JY`AI)i5ziCD^p>(eOrY`{m?&QA9 zlWE=bS68>%@eI{I8_Z`bbIS=!o$Jb_IbocwYrFGvMk%{!uJ%7Y{B?08{wnbVvdkr( zOGm-ASpNX+yLLFdKcNWlXAjC(P37>ZE8Aadh{x6IceK;ITmn>c&meKs;;T%CLyf>NKzUXhRGf0$5`?CB%J2tKQ~54QD5fxn zEzWXD87w*6q~Hyt;E|DnNPOTDLW0>;SqtO^Zc5-Pu_X3x2SJW=Nz`dYFHJi3cRtRI zI&)8&%az(XZqw}l03W!4{J@b!vZ*`Jf>V4%k_p(r6+6GUc_-x@5mSe`*t5K`$jKtc zHj@(!qmb&KD*+f%3jvT0P7V!3@fH9L@0DgK;2;bMVln|BusPs-pz)K&09-7uXMKF_qwpNOC-n< z@n2K9cfzzhZ=LEW=EhrBsba?rh?W1ylmQbol=O@c#h*5I-7SUTC^^li{Bh zmee$(V+1lCKT-|8`%V#Z>Z(|^qN?CS9NRFZg;3HpokPPquASl?Fe$##?jyW{Cns&h zC`a1tBxNHDdm6R7J{w}b?W{%*+a4~_ygTuS;mnI?bPH=XiK_TQ>|#5MUl3bD*HPLQ z!7)71$3C5P8v(W}mvt=asNY?cW0h(VqfyD!qLgoIw;iDF)$M4wwRNmhO}5$mo#KBC ze`DuWGfXu&$1culRI4~gN_c!-{iZ6DinLT`DgADONkvAkA`1M7{Kk8$goaq&ZAL|q zqZn4qte$GF2}NWCHrxVu=z8X|6a5)vdEWjg?j49+DpjjSS z{I||Tfdpy@+;T?mT=uU@rA2$D?QLwIr+fLIntLb8;=HZ4t4*GfdnTo(+xMe)aDvX* zS_{}NAi_8o%GQP#7|RBm2>UWs6m9$4K>*fl^W8)(A#-gwgi9<^e`!SOW0jQ2=MOmH z#?;%trz4CC=wh+4d08Y&7^FBm4Xx9y#Cgwb2;BfODzQ8vT;P*bZY^SLn9L76IT=e= z@>&qYsco$}1F!sTTl-OC^iAi;J~kZVFa8+&A1S?(<7hT zZban$nv!ikdnD6#<+HoJy2kpgR*hM)=H|r?#gf%kepMgYvz!Is42TFg0~r)lg3|DS zMZByC1UL4DzswJR^&R@rS#r;$wCV3u{{ZAm)$7S0`~n~RndP28Zw}tv-b*g8cXz5G zhs)6|+SYMCdByM+=46BdvMGXla#j9f*ciz0Kf^6cQt>iCnx%}o8(TYF+fQnf-&w(O zJh>%+zUZ3q1f?ycXv|SDSzZ|xHn-5aeuMDd#(6YJd^@LUH`hr8#l^JtmiGSuZjCZv zc<)(NZ(;-P!5p$|2Wu!fuSwIBM$=+Zr&vO^>*dWHRtW%#QkVgf7*5%UA2PPmKnH2a z#eJ-@oD}OqafTj_8WC{%wi(uUwcKFmIZ9A%xbt$Twv$j%yOa3^o8zHIaCLDN@l_@5 z7Ap{`M%>9KB?@tjXBEpQ1lvmPb8<;Qr9Z%b2wiEGafo#bJIIiSzJlg3_i!*kk=#M# zn^4J*F=T=WPU69`2m^`LKW5D|Y1i=Sz9`hElIA%CdUmlDoVL!)xbozh-qzY>Tib|ZSfVPE zgCskoQZQC%*h3Kg76nZ5nN7!}gNfz0dZBw|7sB|9lb{Tp&pjAa-~R@zNkR(G_IugmjFb>rV_srEm@{{R$tR>w(~La_1mmbr0%s7t8drmX^LCMebzZH1MUoy%M$ z{J7IMS@7q?gFN^47TzD#BR3B$O`}_xE!ZhCi(j+DFc1k5OfAk; zSe{%49xLIm5$YGW!YzAG@cxyg$825i?c%%D^;xCMY`AtX&jq76UD;U{IF41>FaY)_ zej)f5MzmXB4c$l?rH*Mn!*e4&#oCR6dEHyhHyJyOtDLq#Vo0Td%2n&vqgs_UiCne* zzY2BTNk-{PlqtG(aMsat)1Ni@ek(h?c6&eE)2T+aN#SOvLRoaG;gvpZ9Ba;^t3wo$ zT+xk6Y6){ccbdx^M%OK+xsOcowugP;{c}>fTU|R%SQJgD#7Q$x7?LJQA&i7#jIAmu zC(Xke-nomy9uv3-HH|*T&THx8OL&qTsX1NnjG2YBZ#zL{4k)kL7I@{vzlXr9? z@dd5Mtnh9T+uuVC?C`ceONf5hUgj;4`GCrSN6Z0i?avkB-DAOiCznc>N0UxTgtxY5 zNAVq%^w3@0OSj9O-9@ys!8|gTP{^v62qOs2pjV@S!{%5VT_;B{!_NaNs`zhfDaI|| zm+JAa3Uw&AE>}^)qnw*pQim*0J2k~+d7cuhuYkqFFOCDNw{QCTMOQ^U@rD~ zo1$uLmS1I=UuBl7f2Uj z3p@Fa5n5JdMLF`&A1y`|R4)VP1=95WS5nq*ZfrHHW_ysAvZa)g>5|;ZD@@O*-W4+4 ztIsQzXw2eQ-tz7&N#>n=SK zLD|VB)TJ7doVld+l`AxyT%*m*eOE4xsmHj-_Icw3x|I(DD&w8vNhDHx?g3ZO0g!2% zEnGyCN2cc4!xWLGP|~uyBkTe&8CBGPz~q5|MloJTw-!1zqdYgJNRms-i;J1A zZs$}iCbdZ9m8~O=;UQ->?C7Q@Ms2HSF@$MOoZ~3el)b8{8nJX#Rr#ir9it~`##eB1 zy5_pq3Khv%G@);3qi4$XI9t)G+Pp#Z?eNJQ zk~u=r%pNu+0xn2++zqT%Mj5gQ=~YGZz~J0i-^LhiCOF=5yks0M2wZ*lU_j$J&TFgj zmD_3$rM8s2X49-~ZREO$oK10W8cQ^8icgrLSj>B!N=U>7W>(E~zh#X)LE*~_YwL$I z3mA19uasfmAfyRxHkHIMe)R+ORaWf?|Nv~ML96yCFpow<_H zSv2o;rm<5b_HuEYYf@>#KKxu{+?}+H;}+ao*IrvKC3bn#SC*5U+s;@o5@c>6f!aia zXex2WGw)I~iMS6na!xQZc|M$j`IC=Od9Sav%?n5unwVP)eY$mnZH*#OiR4+u8GHo> zV$q^+Ru1L&Fa)tRLfAT!6(Ty zGD#U$iI^QQyhRH0r%rfh2~?C}7OKU@@^4n96wk%ZL08o7w(x2{X*;M6eYZo}(C+hTzebZ0nw5M8% zl&LvIKZ}xXH%T>SqSKUj(WbX{Y1sEIKgAk{h_#I;LfZzFZ+dSf)-^Q|%OY4>LV!na z_Jo!+GRr!)Reb!QDKaQ^bk}shhp(jC>RKO(wGCct`>WeqOGJXsd&4G`BUxX~bGjBt zZ0)b@?tJTsA|N2zIYP(gvEsS(En3YkCGjw~63uUS7J+qtYpc96!6a=Ae`0v0;L zp55~ts1&lDf|KF3osOB}Zx~w3c^$RSh#;`N(<9V8r@mV&S*E(5N_$7$EHghO6>uTp}Z zAyurSDy!X5P6`r?Y0eHwK4{5%w@rJ|cfVN%n;w@wu-etlw23Xop{v;~#nf$eZ=_hk zJ=~(?TE}e)JQmR$g@!QfxBwCjZu~Cz&1>PkL&O$d3($4#e(PDWNbW84{Wj|IDNH6< z;gwPsR{0k7*>^iDx6Bk2Ik(~sO5eqr<=26{E27)UuXvMAg3HAoBbfwNz8cW{$fTN0 zN>>22@wGxNZ4T$SyD>*HeC!9*{{RMl9IlmNs_9=1E?2_V`Y}lEwadG4cdY9Ai(9)} zOeeTm08567<}`GZWGKq0L1HR%Og;-0mb@N63qrOMR*oW`B~D)2j3)`wRVve!D$ta% z5sc+h7n@M`Vw9xb`F1xGhRmUg%Q0BkVpS!{R-CCtP{q`ZNa8()9!k9#(1i)OQ>Ru@ zP0h}u=Js^g$GYZ#vFO@{sdsbYi|-MSKJG0yS+>+Bz0!oUOLII^rR?*=Wdv^{!vet! zAVnH0?<l)2(#n zk-XbizmD$YAcVwax|T!-%q)4mKUerVlTBfxT=*#7Y6v8sO}NletZz~WSB>wWy0H+; z51OdW9Ex`ycK5G@;u@6kuvv8s1{Rbsc#26z3Y4(il&2ZFVc|L{#&BuMljU!jUaY37 z&ztQsHCqYInAgm)HJ&nr+~rf+LlGHD@#L*I)oYS(l~qx)Nu>zGk~aDF$P0JV+`?32id^qr% z{1@TG)1m7kP);Sz#9F@^3LmD>zBY5{~%IdHDH8SUFRo zu@vgcwHZsArQ<4bgs&vkqX{~SFOoj$ym?}_UASme`qXDt;b%%Pt!__tPIHt}jJ1@e zojz`9H_qjIwwu4&8Xv>I2w%3K_dXiXP+MKxM+3uRu`bANe6-9c%L!*r7@{D_$Qc7M zN#MT?-e_9apP*^5&8Ot=0A+flgGKG0&hgxf@lZA8*D?paKc`H_+gcx(fc5cMxxj4GOSvJQx*A^Xuv42nD(yKV9u=VgX7Cbj?+!Kg5uUG zSsE6AqVLII7FXx)vgD(IyMEAEg4y>Uj(z~pw2gHw{{XbLYrE}QJ6{-TR@&C5J@kLu zI-aL^lh3DH-cKUw_QCDdVM|qx7>bzCF46~g@bADr7V%Nk?)*`w!K&FJ!kTE37^Pcj z% z7rq_PFD_I2e@N4HJF<5ymvCE6cJ8f!QP?%+02pR$00s%$it{o29Xxev__|oSaKu-{ zVk=G+DO8OfTD4_T3NlUAPAXDTx{{N%xoq3|Jg1GLmf>*t3ivvc!_dRgry7*2QgwOh z!NzWJaa5cqX!0cCDB4O_T&K=jL1fk}8dd$z+3(Q`4g!lCjf#C4*eeVk-8mTj4)9cg zd;#H70m0Iv1e|xC2XT)$qLC7i4?YQ zJ2a9iO3{N2s=mY|h1jHztULgocf;Qc7g-Ub)BJ+6#?iVmPd4?ECkoN9C+@O_9ApfN z&mzh(Sx#kMmMRwJ!Z#X_=5(hQS~hW;icRTxLj2H8b0vG4@g{SG&N6%*Y$aRrV{JNe za8+S7hLUPfjO8UAbe*{*)8&=ZQR*TElwkB;=LZLl+~@o$7FPyD*`Jk5bN5aM9=HQP z;AzMf6>vZS03Zd)Cz5bFj-7A^9eK@Q-0H#`or*(7P>BExA0vcNz!e!M2a)u}eSDSI zmDk?%UzzYx_^o~7@7~wG{{St%W|PXR8?ziJB!k?O&>ycjIL-!rO>vsn#2p_(1_;^p zOZ7tL#>Qj|79EHe_hnu?HQkWLNZ$xEiop1R@drfkPlvDkMdDpRS!tHYV2Kcyywopd zMi%;Zoog29@2}-MnmA#OSp;b$j;k6LA2iK>;ma?FUMKODU%so^0;q~S&?b*CEj-3aog(t>k}igIbYwwEgA zY2qJ?TGh{sEbnD&&3{Rr@sm@v(ILIG()2w7LSmk4eO3#Q(%jo4ug>Hw>Ko(^%Od4j zX}&19@y4&=Zw_j@-NVcqQPa)Vx2Rjj`d-)?F!Kramq)tW%98zal{w$|Z-1r#0Kyx6 zrt8i5S?b0xK{jIu{9<{Yxg6cI|$jnWkxGP}MT*EH`9c>BQG zpNVha(suYeT+?rE?#rxEJ)War_7KS;gT3U2;#lI7BtO~Ra!NMe&v6y2V;)N!$1t53 zVsWeMl8z(l>XkX-G5BhZ4bCu(Y0n81=T^x%yTNGBs-a4b8abUz1_m`MQNvz?l__E; zQhv(`S}~iKJly9DLwuCdQc+sTN0oW^iR`t#8sAU2@g3x{Lwk9s*jY51tJ z^(5Imj%}BGZTrASng}=wLeng?4R-d#D&V)=*l+vAj1d>JwygCVZol<(AxYhQ=~;UOr)m%IRiUiWGASm9X^T7YftH zP^l`Clv9#*qc;}f+g47|N-5gM)@5pSvaCKQ6rn>CQl(hbps6~3$`F%D`w2&$Dr(I) z6%_8(?{m(Z!y5R)hsjnP8>zC{Cz1o;9CbWr@T&7@TAD>A%+tgog(Z2M%_bEsX>+Ds-@!hCXmse^$ZQ_Az>; z7hYItLQ;4C0GBYUYc}dGU3f{=Eo~#el6VH1>SPzMk!vJiZb$Qu0rL(LHvT7czyyld z@VCSi_;Gn}@giL&T~kldW0n5JYSBk?boao)Z1A*@%#nq3`Q>Qcl^7HwCpf`Y}2-X#arfu%qw?Yy<&O)C*ia2{I$f;%3usP-fI{MBh+2U~c zY*rd|aPf@?S*nqtio_(Rq*Ys}!laccURs7loz~6kSEY!`ahX!16)4rj)2}L3;_Akq zG$mIHLQ#|*+ofsA#VN(|#ibvJzCL_G_>+A+8uiRR74X%~vrli~O%hq5lI%+?sBSz# zs+n5){^h{Piq>m8CWp&Lv}NJG&HbB7TzoizA}AO8TTu!W6Buacb~^wgu;gcj&jP&P z!+!$&4e<2EuXy(I-^IQrwYEM+lELKC?Vcukg*IA2PxO|KM>}sX?SN(*mQsKk^xxUm z?mO=TPk9t?X%+8^HOshR0YQQ*tGTC0*JsLsQ!9ixP%yo#^GxERlpxhL29=y+%NWI^ z+KrvtR%-H-yLz>?`+P||72-}2HaT}bC*7X+3gl3SrCf(bazG2ZL0t?=JfwKyQ&AZErxF4h}WxY{|+ zMmJ;7R|%!Yz-e=C!Dud#6F6_(NUYLhfN~JyJu(*@kzLNK6p7$nQ*;EVksVR_p$C^^o;JWt(EjvR#y4jUtZ_WJ|4A}KM$;| zn_&B9w{L0-4f_&VV=Tlj2;Lb%82MMOc|OPRS|q*rA>sv7A(}l;NV$+Cj8!AI*K80r zImSx`Zg9-l00Ket{{RKM-S|>l2VK&vo*=m!)F?%jQp3Cny)RIr*#E zo_HTblol&I6W#?mD*ix~${qRGcCl=Yzk7~rgw=HEWYjz>sQH-!-)yn(J4@nVKplAz zoueHT=b)~p?nqO^^T<9_DA}lqtd$C{t3Ev0 zB%{pb9cnnMO780C=oXo;Tj~;~mth>Y+Jw&|%LTaI9lU~faxQKFXzh@K95aU-7!o-( z=id=Lb*E|bYW5x_)#94u86wmCC*bCmeRYypB!OR7)RtKm+CB0l%RRg>7+Dm_<|t)v zIhbmG2=KMHgxkh;Uk6R+}+PD?yq@##r#5&YLm+~)G|iK*4{Z$ z3&v5Ee7-Lo&8S*xT6e?W2CkRk*lg~;*W&GHL1ZIHftGz(;gwtqbe2Vq9ruD(jovVe zAsA%*4%Q*p#8yiW?H{wJOO@4h-ClodTNzR=jvct!Dp*Q*s>(j=#71eg^O*i1Zg1F9 z_A<1Ra=hO>zBnZps&R}WtpwGTFr?%j;ntN6qAo%m<)-qkff5Nk2s z$32C`&9<9h!h6yqF$8OyNQz4YGRq`T3FKx(W+ba^uMqfsqI??BEv)anKXVySo-9<^^0ub2{!--Ldu-C-V#9UZLS%jo%o2QQ=#7H4P(G z)jUO~_-{%0g`{|z$-F*8+h0>S32GhE{QnC1b3OSln!^zXe#+^Ena(0bKC3}1JN?O^q zB;})uo7B1cP=3-HC&oXD`d5nej}Gf!4>a8?!w_h&*lSlJ;>E5F)y?c$#2am(iLEYe zF0IUu0ETzN{{W-_Kwq8pi+_pUCGey^A@MXCtY2hdrTA}Dy|-whwb5-+qtk5Sxf^b- z?H(10pq~1BnV)L3vc6b1=$^g%A!}YJ@YUCbbw7@O4Pdu1#b{-pRkwI&Yg9;8zRxiG z8_HsiHamv*W1Jj{@gIzS3)j9LJ*UHO5`0bY?~87{UExh`;dS4J(pX-mn`#7lRFG;5 zsQsNHy`D?x=C@dZK(Vu_44~B2#NlAMUo2xnpR%Uft2IuIq};isO}!^5^F_@{PWINu z5usJoQllq6cHb-IQk3q}PnD%*O--j|6{hKH^B=-!;mchdYz@Vmse-xxKmN5$S6lT(r{ z25%GDL9EGWb z2cjmSWe3^YT-9wf{d&p(E+LjX`%$*dC2y1WcSJ@)?#?i4cUkxgFTsBX>iX`b@%zDE zInk{y=awxO!#d85bFW|OTIJM|ELNI*wBAgKCG_ts`vFWycXM1=pX}<_gloyga>_L! zhMzo|)=f#%PBDJ-^b2V*pQN_Ww>0W&9JigZHHq=tlS<3F*(rcCV-rqxfQU3sf zd-wz5t>&HM--li!xYBeDV&6KSh2P25yf3ckmyaB`k!bgKkl3m0;&-=YrTU%tA zo-1hOjwg@7?|)#=7JNT%6zZB^i}V}KBGvS}PX%e07ENuc+39ku%PyCFdlkYVo9!hd zYt(``t{_`5AW0&)lIQK8*z4mRw~0O*c!$IHws!s$(7qSLVGX-#I*P+R{fpVlb$xwu zZe;=ow-)>4bzqpIrEe77*%>4NaF z)MszAJ*;IT({5}oRo3PiB(-&wrfF`4$}vM%QSdj1Vb?C~3^Ogxk7sCgNN#Wb(Q&Cy zaRHXwRk%w8u+!Dv1d*b&x3Y^*jaaf;DM;NvO7tHbXx|()UlIH=__yI^p6mV+ud!Lf zsawsaT=;$LZWhw|;@;)b8LeMMxPob|ZV{F%m}83K2_%9@kTtaywQ_Yy!!>pIhuIvw99L&BXHhg&1ZdWV+`?5qCJ7bpD`0`qD`tthI@Ow*_>QGRh8S0LA=yA7uFJTGTXuj2ix>r)iPuS1{=M zUY^#9u3j5tu&|NlgJ~?XMJh(5j#@b#d$xXd_-QO&81dhRuP^kNHJER2th8HuTZ0bB z-wnLaN_H_|N-xZ;75JpToW>)VwcpbzM3;`;9){ z29s6NV6+ikX$^I77yCc$4+3ntj!353CIP_Ce$sZG4Bk?bl`5HIqSTw@k2Pv4cH~^^ zp7FZfxW#CckD62E#O3_4wMuxWQ8=Whep;NibN62&O{Z%l+r8{%_^-rXC)GSl@YBQ^ zCYZWUi!NVM(k(REEWF(^eNsrvLwO~hq;G7aH)d$sXzXCL!nS5FDUsjnt8X5|plDh$ z__Ap)2CBvjyYm^eFyF$Pj8R&y76|5LV+>=Xs&&PDVPmK2{vP<3hzF6oZq^7tA+>LUpAalrOv+Uv=TOLMJg7OtsvU}PjsscC*>QpYul7cYBa z@VmniGuzDqz*PQgcLAERtC~t8txW{PMXP86uObS!)XAYr(C#Y_B0viO9y+A*xf3tR!_un2q30p++B#q;( zCQwj(+ilWom*_WR%Z2h3fDKFl4l>DZz9k#)<)QsHU1>8* zGv@WN$W|MasmVLG?%2eGw1!duP(TEdQXL{hjH2G6sXMX*b08mk1~BX{Q(S zg7b-_l50m|LGxDLMrhV#P3s$N+JV`Ed4U~zSt7j(Hc1%HNtLz|NWj7XfaSR5vQ7>$ z-pSOXBL(`ObCb!>aC&$AI@C?5Ly!w|*C(LQU**#^+w8Cu`PCWwB{_373An4Y(|1pH z?&4afa8%&xQ|4+5Xsbpmm1vZ9NiFv|`-=&um1ekt-tJgrSt9e2 z<-4uFHn2E4kJ>m~8Gm*Ym1#ob?jA}4Jz|S?V zbqI!6%_s*#SmPf-)1E%OgG~E+70O&BhmnS1k}?N7vD<<9;~1`I3URupij-Wnn@W_W zJ6$ekCCuHr?{ydMxZU)|rB>nXFp;RKt5dtJ7}LF*FE`kT4_$m(oJz4qckcc zck{)(LBvZwGIz?8Hb`dN#FM8its@Ps19w$BF}RVE3Vgtf4?)kTN#{nE#sH+LPc*Zf zOq)ZoV5<9q;A95C!S9iZ&KQK?AUsI zyvZoX-HTA0yx`kaUp4NkMsZxpMlp(Uf5AV*I9L7?zaO-cwA(y&uRzNvSDx*S^zLrl z1yHKN4&WD-W%-9g=P7Fhb6&{4a-$$r5lbX$pL=n_ou!Wl2RO!XGm7=Ui&{pbrTDkU zy7bVyXxD!c{7a=nd}W22Yx{jd;(2X^JI%;w(g$Xc#3RBLE=vG@d|6uWQn-pc-AdLt z;x5S@!^aylF(8PW1UNN}ca_&C3dU>aLcv4BldM>YP zJdS*=UhK0d!MKV!T%2Hr4j2rc06gQ9^5EA8ac8NGz}>`7LaWIMP^UaDB1QmXC5gcR z9OD)A^cA9&(teh;?S0pmPWqmbs|d>cvR6+2{qEM=O4iwJeGV$--t~6^_EU|(^9;z1 zocyI;cLWdP9oud&0nexW1<)5-`04PYOVn&^q_Dd2$A_*bNF-E}Xl%6$Yln*}JlNJ^ ztd8pvc6duhKgU5ZRL~`lgffRG2A;7v~tn8!&zsIQEl~W zo6@v?@=U194bqrdYvYxms`{i@-&yYWqyw3ZEJ{jaNQ&mNg+J=Bm{#2uZ=Jkv`% zZ*`2HGFJh2ZN^P}k0g=9b8RMX?Ory@%d|+2x%o_jQ1}3c04~$qlg)i?`$u__YaSZ6 zRWG(3dT9bG{r0?pRq^+mhadr*XDk5Ce7kvXdJ5k|q#Ip5Cwnz6uJYZ_1Zwva6M`5> zE+Gg(*&mcZDp|AY)1yvY@N(pIFtm9+$<*dl=+cd)E^Ei#aZYcWRFH-{^EaNZQQnnQv&L1n12l0hJZ3R!dVjJ?Xt?$ zpFCqMMqNqrOO{rtnP8zNrDw}zlZ>LI(_3^pc)vWvVenXNx{ISaS&T7GwCC+ysjLMm zb)g7Do=}sjKS>oLm*Th~f{{V@aB;WBb1zg6CL&tx7K|99;iB94NKQC-nT%Qkg(O@UGV+u<@ z*++Ad#B;JWdjt#n-CZlzE=~&BgLlk1}n(cDYm4E4J@s?7lCC zc9}<#ob!=Xw7mrA z_U6*U>El*0`OhlFGEVW3RJQHX=kH^3ZtrGBmTvBL zG5Nz7#|#^IC_O9PeKPhmWNq7ug;`f?2PB2Yck~3B(~Mj^h1$=>Z!gORv#f--V)axy^2 z1l5#=_87#HY2F|aZcvYN;azIp5hIV49(U7`1g;bj8F0h^K+wB>Vvz^*rDl(3k~yJ4%e-!7DD>3e_Er)S-Ht82V}t=SUg=gu

m>miwo%Q~N$70Bj+Ol^~D`usPhh9Y`3?SPbVGq+30)J8j*8xtERK zC^#JDv)4H!agYXaUdK1VPl;`$_%~LM!i{)5X)`95rCCn|+NPIn!wqM|5D7@p^oW#( zxxBsmJa(B#?p`@0MQ>=*e`2qR(!*t_c*9@tpMW%5i{wdeuJr`HxxLb3Li1ng9!a>d zV)8RX0ltzucWCC5cHb?IpHsxck~4=VG?KLE6yERMPEK-a%{3Ue7Oc{0$A^pY1BH}j zRcAPQnp8mfLWVVOL| zQ^6(EIFO+ma8E&s_K$^n{m+6Un?~`R7v31rZ^7{ghi-Mt8LVJg;f?MtDIB`S<80wER7|_m^W7}=H51uLM?Uw0296-cr)S!qz$E5+v&Id6w<%8bu9;^Lk_G2aWpZsX}VaM+HN(gLX@e}rsSNU zrwWi&T{%Bz1zXw15URPkoOzM?7a4J;3q8xR7z#LQ6)@A~sY*URyg@!U(XEtdf{_ zNx4DFLZx{G_+2lDb*me#HcJcmW0p~UZFg-Hu-@KBAK9(0?c!8;C$+iR9MVLakIv4> z9h*N*iE@QRpqiVMBT>|sxlPI5PD&fWE@#b3Zdc`8x3T#p2|{$F=F^O0H%=7d-0CRb zmN1n>z5BS{Gm46fZuU<9001O9jo3tW)K*Clv`!(0ESSovVTf{6D-}7(!;s9`rbnho z#7N0J?u^V)rdWgQz>{!=V|zN{&BQZ%< zNG~P~$qGK!lXb%hwHrrdUCRXhcG z#kkX`nw2^C~08K z!5=~fI%107+kbui(fSpNXvQa+ELMbob1Snh2gyJhV(Yqc}fM!*+eU%iZ; zIO4Ic^bI<~*5*i>TSST}C5~Hojl;pUOoYd73}!=+Rbvjh^&L;ITj^IaBN$?WaD)eR zBVw`aTkjK`V1foQ^{8giZ+C?j(T8TjlYkfk3Bdz7$myS7TKz4~Ew^-=zN$%l@1uHr zkIi`|m)dDrTa~qD?QYut0Gisz&$3_mgt-3A(Df^*8Wa}Wp@808+z{i;TXeZ89Akps zb;L}ilm%{apRdj1-wj!5ULe1Y%IiziCzDQ+$57Lvx0=HG6iFP&R_fr(3kjAO=1?;% zGLJ7}qd(HtdL8r<`N`$P;GZ+fU=9x;oE#hx{oZnO*NL?~HXTj}vDK}u@2zATUOCW8 zzc4v<-Ij_$k_53dZZJ8nY)h*;a*Z0!6KQfyY0A^TOWi)s>2^ABzRsOkO05Xanw6(b z*~W3RO4rpmx6Pwhc1_tc<(m%?SYF(VtIr2%v)?+6*SdAnG>a2q0=zA1guCP@Rap>% zNp(0C(6@)|wJ{~yczf(5x)-^(nl|#|0G0D0l>;$eNkrO7DgyfY4w>+$!@3>(x|W>` z^DxMQIj=4nJ75leP?9UTQNRgDc!^W1JG(wwZOfv6!;9v3ZLJ=gy$;IL!pe5S#-%9PZ#uEHuG)8; zz0~%zYT9zx`D?|V6&5f}cO|mgKpA|!ZqZ&>l^xiWzq6J*VQ-lBs=7%sU}d)TIQkcb zHHam+I+lZVd8S@ND@SnzT6w$KDiIX1JXen%6&rM59HWINAY^?rImM*kDvDI^W}1_6aI~V|MJ}zq%Z+I|P7OkT z3UhTir)#98PAXBUcr|zLN*20NTBFCUd>po-?mJeVx$b2UMECGr*vyfQ#TxSFDc08IT$NRi?5ciT?#Eu9KL`tH!M5<-tkMMr zVIBJfa>Fdi1fF7s0{|**3`XOUNvvHObsSVzC$pXB8#%PrsoP(5>2(>kZ7-#bmLhcA zo4oy`d1EBhQ;SVB-Q({)*EAKLwr#fjIjm(9+uO&ht?!5KEDgMCaEf&sdygy2Xs4AF zl5x2fV&D^k!87vk^L#wlOwS=nbbDK9BsQ1uUW2>yv=JEMwYU+eZcNg+#{?WP zWLyvkK)jrm>s`v1w*Dlvi@H#hmG5h$q?F>7u9RA7^?Eab*K}Q}#?8jh+C~!7U2hpU zN!i)nF6!G@`HM%Y!I*jzHNj|%rU#>B?&zU;;KjBEd_0oDKxpHO~_tFxtiYLqX!79EvrD_ARsp4 z+v5zReB5+XRcWauQPhiRr&e-uT^v@jT(+~jSH16jEy-F`YRO5%*|eH!jW{UD-u&*| zjmf>zX?98TUx?IvWDIv2evhO1(aKQ{nQ>_i#+!L&$s#+8q+vCs$;&PdpCZSRnMawG z>b@0tSK*V`+}k|Ywv%1UEz9Y;h1vTCAD_e9zJozQKTay_dJbrS_tWkoE#kV-g~Mj1xnmuWjFv2o!OXu;!bO#S#M$rQfZVBzP8KjLzZ0*AXk zSaWxc`rSLq5{h?CrkZPen$*oPPBWt_wWms7Vxzjf)4GL7$-(WcWS++my1$Jep6c_& zTClZ-@dd5Xk3ouA8Lp9FVz&vb8CFROl1JEz#1413BBAk2y3Vg2o;(^}h4=d8A* zK*B{0jmpmBI3;j_v7Ce2yGiWL@;JL!nOu*UxJCz}vXxPSxa-#(j&oTzUJ#O4)L8>3 zMtG%}qm+O_K3s}G3`b0<8SCj=Qo-SAN;6d8r3*MTq?)qc{O?=d*H*K79My5Sny{25 zQhc*qvWsxlEgH8a(rG87zL&j^AYB&eat5h#j~H#JT_nzN%#3`qfN%8rK(N zO_JUnLh|6tI!PcFa0{Uwyg4%6&IHLFyfKi#2YvDtWkqIEweMPrK-xNK5%?C;*6U&_ z>ghG?x48}evE+M(gp8BsA1merV{Xt-ZK8M+;Z>)G?=AIT5-RJrw*GdhBz9omO(2C{ z9XC#nQ!F21fU!mm6q3($*A66AWkp$*ZCe3^bHib=7>rFxDs*Ymqbx$vrz({cd7%g- ztrsaqPEN@?NyhTrs)j!m8hD&V3_cnWbt~1YU)VIBiWJ-Z^hB^b^rE6F6|f0XSf z(sc`qdt<3h1?B3Yva|lrHwNoco>Yd@OEX1rh)nGuc_-NE1ZwUQQlU=2h`b$bq3P3J z>Ygr3S!JE9mrc^`CDdM7<3y5p;gr3u8X)S9{#gp_fGcFb)cA~jjUe29Lv*u0IYAfFR47(%YJZv#PR-uiAsmVf?F0LWcrzoY%IZ~%qa&=cU zRGjBZloV$kReQ!i0O=FJuM{tJACo2`wigqudWK^I_j6j@i+I{|8A(}1&zM$3aD`b} zx;KnWtRqO&D98>(ZGp%t2**X>tFRf$mcR#q_^IGe8~AhLAH+$Y!1rD(@Qdn}@?1%1 z*K$SnHqz`~4Oc@^9zQobLB zZKcqBMdG`3({<_Pcnp{DEs%mSC8T#bTS;XOOe(yc)%BPh-nDp9_Skxy)hW`Pr3QjH34-Jm-|+s zD$lrm;Tl_c4ID4j^39w8!Ez6&_(Q-x5b({Iv(hwcJvtVX&7I0L*Ee#o084XmJIg$d z5Gn?F8)`dx_dqiWnn@Q{QM zldJ1qEz~WvTj*wr!^65(qRVYJ*rSNY51Q7|OwD(5D#VfC6_!T?`C}}zS@?s)jjM0e zydSA}zr{MNlf8}4iZ5?3;=H`TD`g#yg8C=ebT}q01)Z!Cqgld&80H>WYVB`)A*5>1 z!ENGueLKQ_BYzTJPkE$j)_Sd?Xx?q>&l$MB)b%UrA-2%K`!<(q?AHMjC@(H3|=TS|lr*x!}X=vRN@}yl&H4$8)M8 zY2hJliz7ls@$y~cNf-bb0VG#j;2#3t>wYx0(%^<=u!BdI>rlLiB0am!J-XRKfXEs) zxiHSlFU(Lt!^$}oL*adogVH||_-8`8e+FN8UrvWkzR_q#wdH#5u{4sQN~EVc zvZu(YsL9FBX{kn5x>wg#W}9|b)q54^g`t|x+TT^vw2u(arXuO6XCG+QA&Y9u90q?a zR!yc>U{1vh#|L)oMW}cVeG=YV*lcX{?===lt*s99A;--mg+Ngv?)l28QghBZr+8}l zY<1aP?qa@4rv_>5B^Oq6q@iRp!Ez7p5G!wq#v30gEwmH$M}zghhVsH~b@O6wWnjYQ z^5vS?!^n~eV=k!>An@dKjihC=J7HB)jXLzHD)E$4_LOMFN=duRmeIUoo%UC^*lk$i zsRrjdHD@Yvi*azBO%#&lij(J*WbJRX_HE0l@Cgs_D?+4ysk!q!*8laBmNhE76M^PJR1g`C z71V$}>CSUmH~t=NB36r26T>1Sv=Q9L`>ADE*uxvVLMZ|}g^EJ5DZ?ImSBChr;??zp z$HSV3g)Vf-S|E}|Z8OUa)N)JvnQh&XyxT@G0zxoyS=7JFT?&k`c8w&eMSIe`qaSrE zw-)4^wUWGUlhLGS?N$|Dt8s5g+AdD-M4h7Tt6SUrz0H0j!Kld$YoTgUMRK6V(7n8@ zP`fBDlF4ifl>ylUU@0D1lZx`6h`$)Lj|A$r);D@Kqo~VsAQrZ|H1_v5&Q%$M-@&~i z)1r_rV&^CNZ&WpA+c*7Wi}Fy-ZJQKBseY1QxftmZ3CvI@YsyEYSqiTKY)K7Me^j zw}E1b70RM66t5>P9su1yBEOv4tM5Y6m$8K9DMdv}T=JTFSw*!^naSJUEZoNk$OeImtBqPg~S~;WE{{Ei&9maoH%ryLJ*CNc1kVD+16$j9 zfn<4$Z`m#p)x=U0=IkeMBn8GY&xjrv(X@|%ww@)_>~$?STDQ5@?>sd%=B%$Bw3o42 zi_439Na28)Wms%Nyp1Q65UOEilsujmGwR+E@Fcfy=gAL;G;6u0eWcBKC7d!dvM5vx z?svWvWRsst{C|$PuN1$s@p*PD6@#aTt&YPuQ)-Ohr-yXq?3^6pzOjb28r2l}Q67R+S8P+4XlLkOzvb?sqhC_@og`xnH(H#SJHTl&HZCpgM z*wl)ws$!d|39e|jS{TXCok{!L)3p8T-bp*%wJ)lzLKLHnbpHT$<3=hD9_*5)@X?Bg zD$zzB=7}y>WUP`>+UpWW;{o8aX$zz11H=({gK=A^OjmbyQ)!=I2w{>bq_TT~IlV`Q zTbUE=@*)S4%swZA=SlI7uV)fmKY^vzY_F{3LmYaQ{{V+AuCA_NYlIUuycexv_V03# zPGU*C#fnm)4s-%E_^tMh>E+Gfr&yEaF$p8q^@%0lg#`6V4a#&aIPz3- zl5&3Or>JjNHO0Q6xCn0}n6xvzi7mRv8p|ik z`sSwkSHRx@-B?SVy3d3y)T)^n+s%8cM=WkI$7vx6EHVgQM_To*d&Kv8f5fi{cvUXv zgG%uRmEt@5+jy2nww~ilS(*th$ZsiRgd#P+nvBo#st|ds>BftlXikk7r5+|xZl5*k zQRJ2q$tB9@K4n3+)jPK+$}+K}-AC-)CsI$JCzRr*qZJABs`727=Bg&$Sm@=;6r3Nt zSkwGT9o659?NTYxd<$}rU#x)_`)kOtxYTDbICeJacNMIb@s~*&Gdjvu%zGQQ_+8>v z@h#4W<4qPTjRFlu3Gej%F|Jne^vJyDv3Q>7MGv1KcqEZz5XPg=+E57hHxUC^8}En_ z2%(Bgm7Y1~L9y8n#uSkrKa*=+jBcf2=pO(gQkIK9l%zGs#} zy>eLY>Htz#A1DkLCj+$onA1NGRw)Z88vXQ3+yfc7ELajUatOwGBoUtXG;fA}Ce-bX z_PZp07tv7M-5GBDzwKwXa=Ds0Huy`&jq_@860!ls$@YT zNP}<56B0h_H;{@Hfr3vQbH~0p#;hiXI21p~i zj_MOFyi&ch8<7n2NQxr6)Y~yb8kYU%_FOg+tf6;ER5G`e{Cm>;WAOg~;kK#cO(4T- z4Ys{y99Ga+OR3ntQtltLU+P!0Twcp>Dm3LW-5D)vZpQ zC^>Se)RUB97TjBmxs~>IOI2o>>a0|-v}#q9T@;w12$|GI^(>1Aw3E$tnp6yeTACdHXZ?yGhctpBvj>>bgyy zpK$t%teT#o6|#S!TUJSGNk*avO%cR+xn}_f& zou?JlZs3|FYlQo4l(yG6NJyM4Y^-;f!49R5r~EtkSEbtOUK-Xl%{JES{wf=pg= zhw!cDjS^g4YHfRKs9jvksa{JIEeF~b>MMJBWejcD;8&@M$a%2%iZ$z~IeRw!pT5-S zxl5MQlv8p^D9JY#?C&j(Y8muZY&}X8Whndq0K`raajD4_Zbdeg)8>u6-*()s-1>T7 ziXI==?Ytpx;Y-V}73vyhrF$Ljo#A~SQ`Fjd9ele>XmuIwY;=Jyn=aQ9Y6=l#4*O84 ze)B^37xDAQmU^|%il)(i6L@CoM~2qY*6jGR;uY!IBc9Q1qK{3`d^C*LX2sxReZ{6$zA(dDp+`ODKzv=LaR+_C85_W+Zl?dDt^*b z6r|MShEJKN%><=Vr!#_f8t5}RpQa7M{2s4iLTo6 zX>}FY&n>2xZy36`7P6-8KG`fmm6kZnLhV2$4k{>~m3@J-&0tLr*G zr{ezr72iYlh&*HC8RXV)E^a4LG(%6ZD;9}iIRKPfJu(-M8$_GAA5BeABX>T8_=iPNl4pc2Hva$%d>IsWbF>mp>>E&t47$A1OV8S$P}FX%*~>Cpq7Z|Fzt=9VY+W=> z8rQ;lL@`fjbq!8U^Tlc8$e(DIRQo(hG=p!IZEFp?tgN6pRUrLt9|r2RI`VZQ)H!J@ zN}MAWtp3d_rmXE5M$6sqeC149r|#jCrz!LP@pDE}ZBFl*r!{`DgkgPCl#^+GyL>gi z7hVeRe1uV^ ze3XtkUm-9{E>2GfanGOp4DqjnHD3mJFGsZTUYU8WN2NyunoHkB{j`%K&PbZgnWk5D z9&#h)yp}>sX1$tU7wGy86F~*D=EtB_2$QTv*{{REv zs$n?dtxA;LDB-GRvxKYDsR%xKR;3277`CLR?n*a}o{~#b+~P?p+&MQvy0t4(!9m74 z$+uBds;zX}j9}Z1?)hGgqGv zDnZ&ta&h_t9+Pb(amWOhNhD#C>K1}wI-G5AQZc+R!+Q=$>r`iZDC2u@GjY1*z;prF zvOu6S3bEZM#+bJ%sn|`06YUWt32vg<#n$qp# z33PZcvs|hx5xuw~yyH^+g7o8Q4DftP_@&`{b-lHo;q{$UPr14ftAI55m|J;LK{+a2 z1@hyv4U)oyFYbybHZpzE&N5PUdA;Y1-As#kKBRDZS95BxjiBu(cMm1EF zZ|~EbUAj$jOPR$+FFDM}W+lG5tx`s&mC)bJBcy;`ZY7Pkv&8CW`JGc$(TZj^=p&%)e&_J&r&u%n95@diI(7BK!r? zSsLfU7h1H)+%~bPO?s*U!Zd1;z^Xt4Xu}jB;mN^2TIn7V()0*pw9?-GEh-f&XQfW3I{I4aYt=rM}Q>|J{liJO~JA2J(cI@oiR&D*Jcs-Zw z>+rhPHyRd=tax?{$c>(%4~Mljwzkx4q=DmWeNNtJCl_|dE4nq3DH+0i!8d2-Zxj4I z_{H#h#8*@NKGhpg@U7RKELVC|{{Yz%Xw$|b-*11UY8P_HCz)B3mn*Zj={;SVW|T2A zr$2eA#oL)w_w1dyou#eqdoumbS+BZ&Ei_S ze`wA#62&YGWQ~5vQT?58G2iK?2JV^ozyIYv8wU%k!3L-@jTg!Kp$YqA` zlYIodw%No^(lQwv=%0W;5bVATYw=rI=*wxQYPa^fhO8}95XG^@wAzHQsLj>HaokAk zuEYRLv4q)!;-wmMmD`Ney~l2APB-S~d)`XQ>goDfp6z8SwC_sRog5H2rGA8J;%^Q6!4x zFJyFOIg1a0FDKdru*UZ7{yRgBtjzQ^LeRizWU%L5SImPm+D9)6*>B%WK%Ht)> zt*Uocwug_+R+OZooi`}drzHr&9MGv18nA7}-A#M4TiW(%w9n={#y{{*Zy)>v@#dA{ zJFf%U{A%zmhM@sXN(-N|*l3AwAZt$+YjzS3?F%`)J0i!ZSXgQB>bA|OLu@X!2rX7y zgz}Grz6JOr<6js2WRK%NiM&zap#{dA{tVVUEp2goJU59ZtaUMSX$`!oaTCV21VcT= znqWFD!D$ZP-9OuZTk&?0Yv8+`F4x3XdJW6!I&Puj9RlKIvxa-yJBS9A;tOkwZUZ5jNK!qMJaVVvC&8_H=fgfI_=MK>w*GFhc_dacm?NG@@9f@bV-dk{vcWP< z6UdDW(a4Nc5y;Jb9tSeUyq7w!IMkf!tQ{(9PBHe8sfncLD04=lO4oL9ZMfRY-D{Ru zYBh5lt~~VMsz(z!`!y!u>C>vMG@7)e)KleZ%1Y6`kHo$)d??p^J$d16UrO-?iQ*51 zw>~k_ZTvf`!*LbAiYK|$p3)mg^_>MC@jO2z^~>)_MyaU%mKkGvwT4eN82djFcn4O4 zPk}sF@c#hA)*4-uLTl)BJwoSJ7x79~&dT0tO}(t&Yd5zx*B2Apsw_~$J`9VvAFyov z1MnmEgii}wc+}r~G4ZL@Rc<^_;YNbPP1Wz-V3v0J{{V$$f_)dywY>%@FZ8QDD^NQ( zOLrrwW6XR={gyTFhQ1;&=s&a;ouJ%{gJ*SP;>|Mh`%bw_X;O8MNrzC>WoRaEAQzJ6 zYqV(h?Tuq*Q{_(|3}3U4JgHZQwNj+%*M;vjB_%3xsR_ke?n+OZ(MmM#;=MTGo)U9T zDbt@Ml}>0qAG-NlaphdMNk4k+^Cs+h55iyB_u@Z}btn_T+J2>Gx57W|omgI8Y5ES4 zZ4(u=TL-zcy_V)#BO*JY1Y0EXR69afbf2I)U+hP#X_gb~R~|mTgT>G!A7Q)GEXVeB zl#oW7mf;@lWV>d$Spm6@NH)WqGuBR*(9&Q(-Q<9p3dcfO5$gYf6#kBu~KzYl&T_*Pr(MnE8o#jr7w z%HjzWtTW2e#v0_4u@%?Jm@}^E6C|%`;?IPM;%gbB)wEzNnlkX++s6|u(U8mm217DD zOjL$MWgcM}ByFv~6MQ=Hb*81HJU%2B+9jJm_J)?)d`~UvGPjm3^*njHX^4e&mojg4 zUBR=O?euT8Si6O$g@l&(?;X-WK^s-1l0BmUVBuCb+N2kLImRg@}C#x<7mqdr!fR_941;@jHNY3qKd{B8KB z`x;y6nuf39EgN0&CEleoO{i$vG_k~V=q_VsxO*$9MDfck7c&?OGW z0D=B7v-oB4kKz9Si2fwm__x8DZ-h0+)ip-{0EBh*Nu?IncXqF93R+z>Os^#9TIwn0 zjwM{U!){;PJ!eSJHBYg=scV0Eb*kLWZZ!*7E&l+swEqB{!q->7Ww(Wbg-}XOBOy`0 zZ_Sh8n%{+V`#o0St!*rIy)=fhX|)|bD~3s>Qj#UHm1OcFn*=hiG7N5J>VAeeOrJH4 zC5XdRqgIV6(_d9<4N9tVwdL;Agy#mFQ)-ivOGdru;ZHcturx6^XjO%J7`|xD)?U`E zBPvs;B~DM3!AcW-Dmb^z7Mf8$#`r<|T>j7h03S8GuMPY#@vPeKi0w4i)$Vj_oi_5$ zdwT?w#Wb$+Mr}hyB#{Xd?K{Th+OPBZe$jt%JW@DE3a7Cg0n>~&dh?FF^c;ctec(R_ z>Awp+Q~v-7pMZQVr+9P3cah6uadD?<&X(Gaoive6cWHAUm~D#5Dn#VN98;q%QdL%9 ze#Y>x#s2{9+slnN#IL1kx2)jUEu%W5>Ok`$kX%hM7ZI^wRar(b03B<@%rd2fZ~Hz~ zr-Y0XUeUwa!dCaxqe)s(P2ZVasNVXfdAKSx)kww>N-aflRhP7U&FZ5mLJM6vQ%YJj ztFnH#CH>l$+c5cY*noKKHv{X(e!Nvlb$iteRzy5>ZVx~R`^O%j;QcE;d)OQXNdpXS z`@^1qe8BWM&qL3rdM|NnCeb4ZjtIgqJAnTHdvN;k&3IhZZ}H7rN35-;k9{wGhtxwa zQi^VbUfV%kTgfZEwbYv9#W#@T2y=o);~@Z?@JJD{#t62pBy$JQgz_iKT|YQN&^^)R((XoEwu#r70^l7)CcvRV66GDPBz(;_$h3 zEHvt4Dq-nTiub1H6xGv;($kx6?M5mtQhF=w{{WSbj8A8C;g7eU5JqLyekl0j^6yQO z3550vmlv_Ys81^ISz7!_g^d)L_x$WJ&&e=cL-zZowZEG4{#ls@Z}XI>E?74RBpYpaFc54&)LpUwcd{D*=n>q==ixlNd0Rh#QQ}it%a{br9Mlm zO8AO&sySPk$}TEC>QI-xb@8O}E3pjBF|_4Cz+f8ybDSRF?Ennq=N0O|v!i)m8@wGV z<%AZVBA!6V$O4TnLSz{kXxI)U17ROBk_a{I{vQ36JY3qWmm02(d8p}$Jdda81*NdH zbj(c`_Ko9jx}9QSAlU@g`{N);&x-d*eg*iKMDZegPSy0yD@KFEz7o~+ds{siM+7_X zZ7waX-t|g3x)F&MJAbpav&M*qXPJW*@-bOkr-Q{xt}h7Wqa_+JuTE}s)s*DquV*N= z?CGZD+G<>_*xNJl6A6t~FgRQ`GIa5nEKMqyxzcpwO0{Y(G^u+lN_7&GlCM>`(x$bh zsw<=5&yRPXXz@mi8^4klOw|j3%e#EHwuH7xRXFT22U0p<_?MECZ3bzjag~A?$&fQP zGSS5mcX>`1cnVtqeF3l29Sh)ph&*?tP2z1U!g@}*J6}(yE%v7zmnPZ^HzG)FV0ZFX zXDYwEktB@cGDPG9T@{z??c%K%wdIe2bQQk}L{gnSWRp+xf7eS1LmXmR3J;jZ#Q^y> zsVaS1cq}bQMzpgmH5WAnI!;U4B$Q&}?@}uEiqck!)3wi+!Ewb*uK|V2Ba_y|{Z2JG zE6S}nQk6+mt5=>Y*wvh4dd@0o`%PzLuV?v0%3%^TW@3=aA-E#iW@Md+0vAquigCI2Cl3m_d~j6ov~l%0qgHiXoop;A@}(+N z;~R22w|3N)%{Ko49xQ$dc(=sq7mT!hUcxBv?qjfrO}d8UwY7>(bZ@mIJW;y5u)D;u zScO%XF=o1mfGebb+1uhnY4JsA;y(|%N2%QhhVs(x&BdHok~OZO8^ABbuX}DIx{}eB z5p68bZT5*4Gdq3j@KeEFCDeWq_-^w|(IdM1U8VY4-Lkir0sC~I%3?yL-c7q-FS`*g z(lT@1zr$Y?+Y(NY5IV$e+TEp=W*$H~b$zWKSU1ZxQZ*FUy3>y|Vv?29<#$dk zr|_nS`#tG)h9%dowGDRm>M&6jX!N^q$^?%(!5F^Ht^cQ z@kR>(zGKL;OMUkJmdM`p2UR;yzah_b$)rrSHnRaO}$ zg4#({MC7SxV0)qg+NMK;o|f0)e!YFE2ht(bq_MRK=3P?C8#&(OkbJw_dse+@k`)Z* zKwL=3suXVH=nJn2>#KEe{{YyqSz8ek9Wu>kl1n>?99&0xZj(tYyP3AgsP7~!xCSx_ ztvhS~02ErS;DYM@*5gr#E&iY_7FjMgfrfC=`EW3BtsmLaB?JX^Wh5Q{0JJJ7e&%#k znzOv_nrVB@MQbG+?Cr8ityh;UJS8UT!mOR|c`3QKcXfJ_le3kZa(BACn(O2io(h^< zW`N!OqDe1Ax4L|gMJ=OTz@jLnfRL9A&AvpAFC<{27iGY&Qt(&6{X<-u(?)|xk4=_s zT|U*WUDyU&Q+;)}{WkE*kjrlYf0D`&@~WtValmuK{8ZO2{tnscJ|Wd*TOSc?!YKSZ zr{7sg6n9U#;~Jg7cOeod zCA_iJZuJNL+Pa#_VS9NR)h;e%O)=q>1Qy9}<_VQ>-Y#XC;;{56)TL9NIGjha_VMSH zI!~6R>Pj%OsTy)r<7Mp|a!PhfnDlU1Iu$24)TW~H@M!oRV&mGO(yIktl7eWyfPDJYjXEG~Vm5pWviiUP+8Jq#Uk(~L}{hg`1v4Gug zl6fvIfR_%?i2R~qGwl)vjhp>RY&P+p6l0SO$x4)ETDq%=yq!!%M=xnorCDm->T^?3 zx`bg5XBa_pK`7|=uH{m4RH(`{6}f1_5o!^Nx=ltdGi|PCDK{xf_k7lC$|2H@m2JLh ztaOX@zL}9U<29YVye8$vv)e{v%m~S{MvKg3w#z4-GN+i=;Ewv+?GF@sexYx1ANpt7 zQK?9QGFjY>`PxYmPhq|$?a>${6rZAJ3kD>k`Z z$!u)ABYB}}T1Ktl*re95*ETx#nVXaP^vmQl#W-(kr*%lfx=$=Ce&{s zf?HX1NfS}iMdh`%-l-Lov6$4sJ-CtMYh;?v<~d*}_c4jQtOT+QJ zw|1A3!+BwOBdw*)oa-57Qp`e08zyZ+jf%2J85r#;&EIL7ZT^Si8yF#-FJd2WvrCtf z;jEtV{?O4!8?k~xrfL#Pb8q{T9FZ(>-A6bQZ|A9+;;{0QVzZ9ccvjv7X%HE%veK(W!1<2Qv#AI$PXe(#L*e*s8rI6sRZUh4m}5Rn z_P|=qj?$&fMfbBsaRWxXGMJep-WdohUtz~d9G2VWQA>G z4=YHBRz@l}6!}03G6?ez7kD2`gv!yuE}Y`wgi3tJws#nC5ex5D3djy5KRU=d0;5l= z;IWo)i^EQGol2>EF09;Slv;MD2PWpd*?eB|Yu!`zoNf;3$yTKpdn!-u`#OBka+II( z8jI!l)ww!08sZr(B!+pduFfQv?504TNLfkRhkAK<+U(7W z^U?b{{5>{WmF4Zma>&sg_;<&!Kr`~)uAQ5Vl)azu(t=Wxa8lKnY)`j? zgrcfKE?k_+QmIawoMe=is!7Gw{v?}iM$@yh_^5m*_y#~NrTD)%_Q z?uG*I+^@UY)VBRB?QYi6*0zT+AA@ZkONh||v;bYY+9`%9OS2IsBoV73s(|w!k%%~E z12ul z3qP6XswmpBh~s0mRDq440oNw0eWO%{7$i*nx)}tJfPAKihRAO8w-jZEb7YWWH&na?*HO_sYJymd&n= zYMXb=_VQb^F~NU1qX4)8RxiF!8+~~wtuCRQi`_2cXgnmaxma!xRRuiiQ3*ck|dHj1@z(+nq^3*f;%Cf zHdvxAjJL9aNp~So1YoC-6mc#o#!8JI- zWq$~|w6eMgVzFyha3dD>&`LMCAx6by1&Id)rbcs|)F;9x%SoLY65E0#A3n+>!$o6ayiHQFIM|=<@l!xxXbQRL3m!n-< zL|SMaZET83W@0-n?wORuZEbSENi1wU&pzfzP=X>=iGeJ!EN3dxEu}4QcJ@zgce>TP zUgbRb0V~$XFMQ{poF@`9>1;%*X zH+~|pwGRtVWgtkryTDagygLa5kGRTk-!EcU1Q2tMYwMfe1c4h|TtF`NIo}LYGs_wP zq|H7P%ZdP9P?nR2WmAGhOQd)^O}v%}md!07xP6UsBU^=q!P}CaYO&*x8PQKr!y`2u z!6fGF(!J7(OGR~UT(s_^uDTNNP1z-DwaVSwdTXYOvhqGGpG>@u0qpJ+I2a)@_eOt& zV}LW$J@5z^h-vaWD#L9f92|(_X-Ox7SyVFueMsX29YubE>plR{ts_;m@lJ`Uf{eEi zofhKWdtkn;=Sdz_fCbh<2P`s14=TP9(xFY|AX!EpIj!JekJlW!sRx6cf=MHRjL{s{ zoT8e8*K4W8x3#S}MoYfWOFpQX<M}6Si0plB(GqaB@CUdBDl9wCwyVZ+`PJyAfNm zZSs=UZi~1C9qh&sgE=4uBnIv(<&VLeEk;v3QLL(u^9iGp2<9Lhso1jS2<<&?eF^psP(_@tziUfad*snHCl5~Adxc&&MU7cCaial7?RUv2e2Gc5cU z1dT1zBEsi9#Ti#4Jefj|nohW5mH?BU^`ZX&2*Riv41l1(EQ~-?{2_?xoMbOjM(zNw zs(eN8PsCmnmesWwr}A}DtqjowILP^xpjKlU&VP-G_0c*5L8J+_r)GH=1POWQ*xTd{AnaD$v2WRZ*t zg`VM}`Da=*-Lz7uqkHzV(R8+pzJqx^cDbWUa$Q=Bdpljfd!^rAjVqrWX*zntGMH^; zjG)+y94!*2S)GVwRcvL*BOH)&GsRw?z^keUxw3-dJCYkB+SX~|e4WBMk~D3scmxG3 z7}wgcd;``kG;K>zhgk5HzPV*?OdcL%HO<4_i1#J5?KrW5Ia?^D(rKbz&fRO|Plz5R z`1#ddVWie+?V=oub0XxIW*3;_eDYR)oiF{`So0B`{g%6K0)%y3TQlenHRMsP7&HoqG# zFK^Z_7NZaqh&MXh*#?@et@JQ49C*3JfD zcO~zJq6unLv8N}f?j=h2;N)RI+br_E%g3DcBh-pVahjrGwkR^Ewf z(ZvchswU(+;sR<~k>%1MkT&?=RDoRpHT(GSw za8ry^P?VTC6&xI^H7by&qm)~n6*)M!rAS7crw3_ryIJ{s z8iQ%dv02(d3PqGvx3^eCC{Ffh#3%%N^O93;PD$huUfJ-+T-SU}s|`0%)eX**ZE1IR zd8X@;4O#ERcJfIbwUb_~#@(j5SiqS~VkOJ@fPib*Wbp6ov90NI*}-Y?58?j+h!=Ck zd8=Al>zZS+janGtyR*55Z?ng^3EAvb+D|o6P6c_df%F?M5By91$r$_Z!p<>_le?(&X{gJVN*`%chv;Gct5Q{R>}4!WVOpEQViih?6(=~w%8P|8OgZOH zQTM4q^Cp~P+#J5o@z=rs00MX?_Dt74D|liZFnHI-n&yL`_?`_a(mreae zq#AYY#;Ip2UfkN0I;thAPb9+50G}l4UM!1K_zU4pKIN?b({b?^;x3D==~7r}_xgUb zpy_%xk0yr|=96@bX_72W&>@U^|>y{8QeR@d&N z&~!U{pDN;4(V~b;aj(GOELwHH_KcBO-OV78rIztxvvL*B!*faF)Sp_kW24RCSG$Se z(>z0AbA6)7ZQzSfxVh4|W>c~csk z>PDY5VTby(Fz{TGi=|1_{na?da{DN^E_UiKUcMjdaHmQXqZmsrRC!|`X=ggJsVb9q zQgd;FbCjjboTY2Ua-N^3!*SwIg~-@zY@nm2&0B+>1z{0S^~xA)NaUtX5S zOug{~+(V~1x{lU)qk9*(M2`u6w$a?Q=Vte}J2(Cq>;5UY_#@&U5a_-M(vOLJ5B7Rz{Lj<}76S0bx?0C?lrSz|Yj+Yx{b#je2sWLYz~p z2ROM^sQFYKB?T%Gq}+X_Ny)b=?os57o09OcFqIl=bR`*8oS!6|Y^g@>PA%RwT$E+( z;TYLM4PD85ui?Lh%c$FYEKNV+E~l$$zBbo&U0h$XYa>tB?d|QZUe``Kb;Xs?c%T}5 zHl_&dWGQglnL|j=UfrPD=o&?#iu!y10Ej5}M%m<-Rq}OB8YGTIZ#wqk;t{C7m=wGd z%`M6#0~;Ffw*L;$*kA?n6C8O zqp4`xed5>vZzoF|+XzwCL}M_ywz#+~%%rhLjo6X{HaS}Q1&G7ObonY#g*h%;DSIlA zQTQO5il;lbtXhk0t4i&sErwugn zm@c$6w~=K2($k|;{*4XIt6dpk86-W-D>JDX3KTe2$RH9jx|(l_d^ccB`gNA8rRurz z?dOW}=36_1%E<3)B%dluIg%kBR9KNIAy+Q|xw3U`gVh7Dw?a~B@zb)l?l0VEdwDL{>Vb=q#RH0Qg z=I;I_CgT_C+G(ey-l_b~IYO)&YAVU6qULF(ylnJp)^=K6?e169{8KipsbzeNcWtNQ zbX#pUDJ1h)h9}I9BRk2GP7YW%VmTg7;@cQ?j6rp0CB?Uy=3D)$JWB|XNM~8VCJ7g6 zghX|8BrpJ;eF_aDS<-F{u~=V~+!9ds5p7d)bxAH#*%rg??s%l ze2Oh|C7* z8xgBG{W9>cg**dqs=;~UO+IZ-FcI3yP0`!#>RDf8uZ(g_BJvG!zqOp+6~EHH6X@Rz z{4loqG(rbd|mlQ8onzZhxXXWQ=v|zYD$FX1v-inx?Ii0 zH5Vw$mz_ztsM*_3&QFi}&CH(-tf1BP33Usv4`>#ea!GM<_Q+tKZ~LMSZ){( z);=5R`c!tFBk_ilJ?*95pM8Jf9V*&wK1*BuZ_AzwU-(KQn&~d|%{Ib0oq|DUs5G-1 zSwpXoQcO{!YMS?lyek#Xr+1>s1)Nqo)}N!elkJzz3QQAFks@`1Hva%n;>0}4ca)2E z)&6|qgsVddg{co_sbec*Dmlidx}}DMVGm^+NyYolGFFS6qZXCq&)4$iqgK6mOWJc` z>ClRdqwh+cS#!=+8p@W?4<76Q8>Sdn$?eoEUb+2YBTCHtKC}JX%>^-YBw|4 zOp>$4meIM7VL}Y^nBv@anK=NispC23(=0XJL&K6z64u%T(=@wC9{pL?Mrppq047Pn zC@$nwW=AW%g)fXH(tJ0j_-@|fLu|ja)RhaVF`p1{cX~!AUHb!+fl$LU?>Ll`5XW z)~hPjJ*=XqP7|pZsKON~IL7fxbA;+tjHKeVT&JV$B^tGooO#qK#t`IA(rPWYHl@t$ z-z;RHnn~?;iT)>ELe??qKMVX*s~d+4sLZz3HU~#hgb8^jp*5(GI3H*!1536EQQcHO zH?DputZ@^hcuF4-%v~dEO%uc(9Jrl`kwG&$YJNmPIo#98rPN_}6N4R>g7nK-R$wD= z97rRc_U?GyzyVrB5ky%+g-{D0yTKx@OW>_0`u_k;X=1grgU#61x_0|z!$Bhwhsy_Z zumVEGvI`YZ*cDM(I+TCerO2TtFZPUEb7?cIgP27n*bB+D1T%4kp z?&$lf_PTz`*0X%deA=hV?Q7DD;_rxj^98TL&k)^CuZxAT)jTsg+inBpnc~%2IQRsv z;xmF!kQ)mh#$OP5b1Xjz^=6%~($nm6c!$EVT}bJ)`TLt#ScE%|k^?%)z9;!X!LF9$ z;r{@HCc2twEL(PCjN;D}o>v+BNZQE1XW*_t!Pe%8J7T&#; z6>IgsHpwK>nP>4A#kT=I)9|kT!*oTVf&4|`hLM378~lx7+B8NhzDYKzZ8OA7-6u}p*dBIZ&B1~rukzJ-eRh*S5i=N zx=ke}rJ_dASc+WotyNTtgqus3o85fP+B9PBqNQZ7%Jb~;tzzD3X;r69x-(P5=?3cZMlC6F`>=CPSDKQ$R+9Fz zDayTCHK7T@4wUEn$hcKa$tWo{pDSrOsNO9>rj^r2t2c$Nyvwb2^6th|wU5fR)peat zJvU95ym5(+l-Dyub#pKbN&7r(3~E(L3`1?{dWF83rD-w?SoKG@x&?1FDF&V4uP!Ou z%Kp#Mu38JddTW^WgqT>|#UzJlkf;@ztQ&aFnH+^}lTeOd?E7fMde*%vLL*t8TX8+U zo2D+-e=E+sY1Om)msKP--e0s|*xSQlBsP{J-QbGYe`)L2mV3%vO+C!NVbiSc8Z{)r z6Wk<2U=q0m*UI7-w1d8hYTAm53b%9y(cKirFSc6+@(8f7k*!c zDJI%nx7OXQ^jC+xMw}xi8fkgUGg_aeQ&4@Wjp6bFqyS&9< zR50^z+CyB`ruavyYntS~Ak-$a)O5)#ZFN0SVYZfC_p1z6{v0<$dTiYz$1Ru){zG7u zOnXk1J?k{GLkj4cOwpLq%Gx+JFB09j1Irh8LRfU|HJISfAKIn}{{SjGkO|;EKUnEr zAoy3QcxO)2Vb?rQb**TcmYw0PI_WR^uWRfK{0>^vj!Z{dEeqdlx1BXg^1QT>ABPQACdvP)a7Jq4p$ zz|%$&Um!rKD03MyhZtN}p!jcI(lppLi`#pv8zs~r)6A_u%PrYkn|4^>kZ!^P0!9Mv zbGIA1H>-=r$-2%kRGXB!7sn-eb89NR@?Pt9<%+Xz+HDw2G~%f%HyFn9v|5XDvTiB~ zLh_Vi-QAi=xoEBJ9s}?$kKl5a{uI%4zYf^yFjz+-Y{&dde-})MxXh66w~4<>7+d37w&u zK+(q2d5q3md9RW@Iji{3U(_w_dc@iIPv< zuxVv^GND2o^4gEW{{SBNw@t9T__b@}K$>reZ*DwW;oAc3Wv7dal3|+AN|0RL17cvf zxL9=41X4TNrPPZEyO-xHQ&sBIoqCRRr6?&lb569Q?{dW`w)k!UUKgtM2D^&NyQ<%7j?{{R%e4g6a1FNC$vh+h|eB;MNH z+B7oh-UaZT>uFvS(=Fp65=}z+p3Lf(h-PvTjm4;F%&6ql|GvbdI3Gu$VeaEK!qY>r1=_@k}(%fWXZ z7u2;6wd=NWs_GY)Hos`JmI&n9_P08Bn*^(dx7dfwVq7^PLjh9^9ZW7K4J^M43OHF* zUfUO19@`T-e$wtyl;Y`9rBVr7*u&c<`DIgfL~7yjIC`*-Dvex47)zfILan`(M+B5A zILcCUa^_O@ljKrPN-5nRBI(*Ly(qhb!`djlv9!2LjZ?>dCz{?H2?9kP*R+=AL2q;s z6JF6`A%h-0;R zqF~C-KF%H2qw&wf--sIh;J=Sh)pgA_=HfWCUkh1T&8MU>x*+>Ln`G@A465aXg>Nq= zJhH)(61cDUSKc9l_Q%88?u~Kb4KDU;6!9(Ap<^Yct7&f(u}ylGvB*M5(?b-N;KM7V z&nVB94Stb>qlA?hRjG)lQXb-zQ{?1vO8n50QgeDMLJ&=~;VV98@c7x|BZ!?SVdn~* z)08i2p3*XMi?u~5N7(7_IW*#~r600;Z^G}{$6b9pK>e13{j3rjj{Enq42}Tx@?*!ihOAgd2t@+%6E!{RH;6;3OeH%=8&QK+fG`?US#&C44m<98JAc)iS{m}4+> zmJX~^rxz*7G`TH5e(T(D=WbucNx3h2$+v%-z6*FaO@ZZ_MDZ1_nWSE9(5^Km{>QVw zym+KrsWjaYo(t$>^31E{U0Fkj*@~tV<7eU@#b1XOQR;echNRN}^Jj=Y3_p&%X!?=x#NGtbY-PANcW_)=HO9Rxo=d#XX%J;i#x}&QbXckZ z<)Jmpim6%*5@%)sv@A5lS(fVwAS_ZWD@? zMJB!^xm&uj(*0kDbv<8K@cUoiczvuVNFU9P-uA;*vsy9%5nlB;0t zBX}!X){AImSd1;^7|WD|tFi({`5VbB*kV8-xd)O4IP?t*OdcE3H2ovPR#x&^?jn21 zLAF3x;pb=xxM}7MyUYy87=po$;s-%vp)_;PbEr#YbgzZCXl+fk!Gz~@GZ6ACVfK|^ z6dk`ZfN@-OGhAYwG~BAwi?q49V$yB5B~iB9vRc}DT{kTm=Hh8#9ICfUG`Z&a6lC1r zOFDe7k@e(ri|W#|zl+??wv7x{u}^fww)d2{kbwUHHWQU&7-Ssth8?R?7eG-;I<$yb z0)!Oa?0bwL`M&u85>5_9dW`-R)2`-06h#*d0t}YiQZlCC<7xa#Nw>0AvQI|tuC?Vyn>;-wB%@L< zoi^b8$*EsY=50M2y0UhPZL^3E6GmEGss;+Bh(jY68$!N8LhX&XAcKmxr$&~dSG{>B zl5Te7n4(2LyNW3Dg;g11+e16C-H@wYEyso7e<~Y&LMa@OVpod`CfpLs^D`5)5)RA* zf-}&){5N?NPyUe$OOKTTl1lTqvjMnm19u8Z&jPwuI}KTTwdu)0+1gJ@J(JO`6YlcFhA#6xPMQ;~pCu_+!Wp>ipKD&+S!DZSFc&UeM`&JKrUj!LNzQwedHF zFQF}ulnGiWwvgCYC7&a1N)fnWmcJN(WWU)C%j2JhJYnN&?-1*HL|RvjwG9T+&qNR{ z!(G|fSYAhb@=o!ziay+85Ef<6%v26*^?&x8)V|5^KjIU--z?fh5H3g=^Ytqv>yy;C z01^&s!9U=fi7kh~&0gUYV^sKw;yb;}a7j%+L4zY0ErS@zI0L3@-@(qM9D_1(<^AS2 z2TN5MMa8Mj*-1%hZ8Uaz*zu&L49bL{{pCue)~#!3!&`rKTV-RD@TcrM;_nK0_rm@t z(RFPD#J&-Uz|%>o%_M63Z8uhir(GAY?h{%aT-rKZszDymQmSlai@U zuCbjdb3#!{E15LgYBpM>%PU4Plx-BPWOr1niJp&=S57v1Hy3wjcCX6h++EYw(&l=f zogWDQ0A(+UUJLN%nXFtzr0Cu()8__#EMMErb$GGMv8HWO+F5L1V-XVC7_P?X-dLw7 z_(S*HHyU-emmR-|HJvIwQW#P@nZDO)1FVHJvf?oy0pl1~axlaf$=$f#hs2skn>0;* z<`|`D+{uz6lq!=805aJQr3f2NPa_$x7}vZZqbG}}@g>xHoca~yXxfIC4Xa#91@Jot ztaia$ww2$ylSy6K+o@i( zDN?G`VMmoyoN2{18*=iw^IflXHmvUNc9yTxFKl#Eria9t=_!Dnqj8BLlqG zw7p7OeLCLH?3WsRQ>>H3L&bEK!B{1{NL8bF*@`TR&W#dobl%Car_-;rnGu&NcPx>- zOsssP78HaIqjMo6jtK-62b#P#HKx6zdaL_ChiC5Vt=qemo6#?lsZo=Ql4?tt+DhAL zZ5O@d+eu#bvbFqT8=3s6H0FD_n(5{u_T3%Dywf0GF(E)fc4Aq}E>d0cDd%-nwb6#3 zZ*4WJSy-_B#O~;Se37F{%!IZ5bFiJ;Ltqv)>{7*3m+;>z zZu5opl(xD~*G;|d)NOlS?B#Kix@%b8*65Q@dp57N`u+z$d3~i_TVh+OEgjZK%0+5p zg|}^1m19&9M%Rj-J;ai$rlY6s%y%~uZoKla8BN@BktXQ!5*`^< z6>vvx^70EihUI3B@_tMSBan~1wX%grPBt+d@^g`CY~{8w&6qCX+K23~y%TQHgmzHP zgaa5VN$NlxS7d6sDL77QQeOZ5M<(W`YyZElOLndUl; zuBl-RP-&XxsirlwspZ?jb#)X93bcDxC1D?zvB(GkQa)uF9CI_>`02&j{{V!)Ra8)^ z8T)m>2*V||s=vrFw zm7!j=Qnl@9so8vz?WMHf?~je;jHJFZ@dp4Mk?R-8hbl0nq`?0Gv&SRYiLNJ7?qWqmQqFcpsuO@K=zE<96S@RtR>sf}chAe$ zBLp7*0MeuyB#4nKLQF`Fg4s-2R+TwMo3`O8uV#LJcniS#CHIg1G_1NNoh*8Hi1bZ5 z(h2QhG1>@hbsscFHWY}nATAWH;-I%o*QuX|dN$K@7L{nFT!Ia}Jc6ONqXjv^1cG`3 zIp(_Gg8DjM_>1GFps_rrZ;M*Js+EbQZJK-E+w4&u=Gvvk2?J>Zq2j&%KZl+o*5!`h zM$zt>HxSaeNMHqk$&saH+E9GO0<&O(0LZUP5uDYhRmbZSgn1})b5)dLuSSgC^GjDY z-L-A%+tA~uf~Pus&YkZm+eY1$NyU7v9Xea@K3j{!HlbA`w_^?pv}6n^+n<|$6?PxG zbG3Tpb6rihftnk5^)}Eo1k#Hnf7&+|t#4~2j-)7pN!1qWHaz*z84wT#?3K^f{uuq9 zwIh5N#BxDx5uKf08<-l_c$Llsvowow5h^msEac;j!0noZ`LKZWd7wSnf{YBO5~l4;}L<;byznXThfD-@5+<8x;`WApR&`tZ+& z{44NlO7QiTnPF?GT=<3;iuwz41h+6k(KMsXXMBf6A=H)g0VQ^`Z5d$rmQ}I1OdF0T zml0l_E@vq6^K(j1nJ;-qmKRFS)^6(VBddd^sbXtJG}TH`l$Ez}w=X(rwE1S*aZj0Z zCe^Hbllv`vCDh04+oSmHAhn*yRM+*#o*{7rcb1R~q>V0Sf@ecAJdz?R!X%XpfRzdu zj=cDK)ZHpH5^QEXlB>An@s?l@1Z7Tm=quZ=~J3XK|(X+ zr_9u)?>X!ZpvvB(dYRF!rh zk&(E9LC8GU=q|mW{hv{^Nus*Ci${2_froNxvp~$C?}Vd5hH^Mddb=LdvRtMIAQSBt1eY9Wl<%|%F}Rn*K0jDN$S@_L-td@<4Pe`h~~mlsps*)*OHww8I(BD;)v+J*BeSj@KWpk!`RPTw&} zBpSEz6ZTxu{wLiX58`IEtm?iNdD*-_;jI$pZwy(^7EmBgH zsMCD6QBAs0lf0U0E8eoVT@mxgh_%m$9uv8pJV)aX2t{)l-qhGT`BBg1ncoV368wGP?|_~e@hrBV1oYn!>o&S|?xj0;_s0HI znw{I;C7es9_7N-A@4nr<>+x?>r%rZuxGOWmwxd1Ab zI6l|=8+fzgAMG3B+usx3YF`HQe+hUR^2YmD@IQq-L1*y?#&X|Wq_XMO-X^+%^-U*5 zw}xa}seHTm?xeZ5iro>!j;HbSTGNwN(r;mrWSS?9<(3h4_A%WoX}nv{c(B~d1-p<| z>EnV|Xp3x6NHzK){{RG<@n?m;9O~Z^J|0}Ig`?~KBa=Ci3Nbds*A%kybYKxR)lUm*p6m*>yUutSLWfIQKebnvABsoj5`impz=LdD*#MP>SS~l5MSI+Kc^l_<``# z!M_otntvVWI!?A?xQ_K@)NC#M$RxHZEv2=*k|8C#TaD2yaXOZb%3!ECt$X3iTSFVz zskYOt?bU4{MTu4rqZVk=DIP_XDkF|QRbqugfE96Cel77d`c|i>$K+Yw>3Y;3XIMm% ztgAZ6=IxOLZ2-Q7JfjV~w=t!_c}mQ!2G{U!82Im4wz2UImXCe*E4v*lRlD%D{-DNK zbs6AU?xL}}wuwp2qvF-AJl`^Vc$HQ~cdyKFxamfnI7+kjbeoMjE=|Ik(MysNx{RKQ zxT{&&H*@Z1gmRpu=|`TcT+>R@maVRNB%8B)H=@^Lzp}U*T3^l~XG0vRwi~yDWVZ;( z4dhsKSsiW~D4sVVW{z1C4Y&j17i*_$8e~`2*D*EvYC>DxF5#{qa>iT8l64nL8eC0w zZKsWVvm#C8c}iQzP`;Vx>E0;OTxv7hT3=si%s1&XMSX5sJBvu+k`lAR@~yt1C9Kw$ z8xT(#$daTE%BSaTPr_az(sd0{ZXR1(=H8%}Uv$Y3;-ptg$4G7%*D| zXxU;^BhLIlA=E8yW7IA7-$E}e?cu(at}W!A(nTSx8sV9InbBH!Sq|HaD6TMB0Tst; zn%<>xbFRaw$91D4YcuLPbV;^%i&C+i&uis55aHV9HE2sJvO5UfGNjgji2P5gm6qkL z(@2Q-cTv-!XS}nTdn;=xG~3u26Lf{c-ihNg+ca#} z1ee<5xl-{giu8RU4v2@4e5Fb?vH ztwN)XR~JfBad%wTZ<|)FWR$c`HKVq-Z#YTNuT4rE&ZJUyx=t44aZBFjcZ*VYP5rC= zo+Cl=&C?f~HuErsOHmAw#M46+!WXuhGUFlb?;^L8%!KAWxkH>+LihTPuD4e$;w_gt zb7|L7>DN*)d(wtz&CQ9Ek1K1mMi|IGVmy+l5~DwyX?jJi#l`3LZPao}7n&kyWmoeg zjnP^XybxJgp9~jtQOH*WRSUa~M@f>&jfb0MX3uicTFR#S-Zyt!mKO6E(s-a~mE96{ zeX{}=D}$99l_N$on{H0)o-%yS(_a*nw2irC?{g-Wt6e%L3UjR}N8yT3l5tno4$3^q z^EY`XWVcd#SoKX`MAKc&yF}32%OtVMBxPhpza~j7*+|^06tg;PBML_BVC4LX@h3s? zkAwAA*7S*_)U@TlkxliaMYSk_No5w=#jUcFaS|0CMxi1}8nD?U%Pf(G_njN!Zkeo^ z?XDUdhe-rtYbgfF?9IWR+Ua7PA(4_7NbaL!6ZwfCLfk3ex(PB(G(_&Zh9*KnGF!_K z+GgGhDK8_UOp+i6c=@qj#HU9w!@4T9r3ku_lp0f~H5qcn#pvMqQfV~RuAf)rC|1B% zb)`kgO{hu}O~!D#ap5XT^PP8whlh3^H5CZjmjtagBC(p5QT^2j z&sL>+i%6~P)jeJMS$UtHM+r^eo~)y%GEt`9y;HQ(T5EKl$obnvw6nIF7%!{^@Md$i zX>KBu=K*&|fCg>S>l zw2En3Q#<)4P|_-+GDzogLc2qV)a?bCw(et`rHiVcJgChl8-Eg zal=z_P>oo-J)C73q@J5AYP3zg9k)EP<3Yc)wQFnrGHK-hDQ;EEZF6P zF$Cw1mC9Z_+AwzeOaOq56GR(%T%Fj!B$8BdfHDtJ$F%Ai7Lg>uBh}?V;Z^N!3#FuO zxDd)=1UNU#W9hFG6VzFT{HUNM;CH!(XA&P&D%1KbKB ziHcW}l&+gQc6un)86Q{v}v^sT*V!< zQ7jRUHty!)WsXZIOBCL)kX_W2V4%JO0x)a5(mX4!UtYv*MXS6D8Yg1KH*ibD11>IQ zjI!<}m~UYbjrO|ro*&Wv7->4@p{eMwTxr)A`dPMj)K=Y=?D>+&VYq1CNYPoOBspOt zZa!%k2EAug@t1}*D+>mfN7D5DPfvkEYFcy<+dac7ZDoktDv=8ke|NwPRDr;*Tt+fV zN;GIq#z|gMii?A3w&fmY&aT{FESp!ou5?nvM$&aE!AdRJMpsfvtrV=eTaLQM&Gpdn zYfUdx)Ab1=yNX+8o+%-^v_!;L7V(hgDg5y>2%YgG4DV+|CGeG{ropF0YbCNnX&t)H zB;^O5mrWx%W{gT^BVc2;Fv?LB0008D7gc-ZxV)16;8bnCOtCwO^xMzq(BjFunjs=g)Ms$BHVOJnGB!PR=%DxpKrH&myzw@j%QXaaL}qVz!a*ZC}cd7=sp>@(#&pfu~hwCR_2QcQHak*7?z786<eHk*n{ZL2G8udl?pnlIV- zPTKzfQoN2Y5M61JvoF}9noP84&GS6bF4D??5<-(!dPYT4Th&0MJlW}8iGji`O%-1V|hbGxmXkOpk@G*$;j)puNv!i zmQvVh*A~#hGVYl!^s5`eCP7e9?=9wa$ME@XtJf-VUqS1-kk{;FvbMB?P`8Rm{>i6m z1#YaZWh6(vVRI(wt>R}f$+OIIp;(a24jtB?q7{MleHz;84LT^`w^?jiB~5|lynQ~- zIE-l&rC~wlq-^C1ka!fnxe3B5tp&|@XemZXCCcK|C9T`ncN^Z%y(~L~q~TSx(tPqw zHtzY8l5b^p`mGhUcKO!I&%#$4^g6eTo^4Iwm&|J`c%!qmb-*Ae?=&@Sjz7~T zv&(CEww71(UPo~&?t@Xcm1IkHfMHrYke_ECx=_1tC=Y{B+08bkJK5e?rO;c&xU-JV zHhYj{D{T;o6(Wt!$b6&BV_eo(s`$<(5cA<(rJNG*|Z^GLfORHv=M!^Q)Yo4AmjR!c#6IC}(rCxctH7{cxX~DN1 zRVNo{skus0(I=udsfMXlMoxqss#B-S8|bP_mNK>VN?W+uC98Y0!Xx-|qcl*vc+y=q zLIHTLVQs3xM@b=;1Dy3NNMb$ew}~|W01W8&7WSHMr+;)Jw~y^wfYjyNJ;5!xqfO*Q zplu*!h#BW3SKIoZ?9HI~uS&VNxzz3Lyl$2b_Se?ZgQCxO6}w4bmk`Ewn`tCi?e0QE z&J3Al>t0RZ582mehwkrwDflMWO4P4)39R(Hn>ivc_9P@rGqsbv7PoG}B!tS*ypXsD zJ7fcz8P*PJrAcEdPE;nLEHAUA8Ps(z%TkJ$vz8*1V;MWfOP0;b3AmceF0U4;#}5em zNU5s4)g>4xYspgF(WNHZwbQzGjJHS0vqhlIB1w0DJe!yR>pV?7tbXVZByRFK;9-j% z0322d=sI7CbvvsBn^&>>9lOq#GCIWt%K$<`vlxGN(gTx%LY`GdE9q|X8E3&yOFNn9g1W?&u{5Cd` z!X7!~(rz^QV`&hO$qkOFa|WRsCI~V8nOv|6icT}r4C4(_3V1ozsVPRuyHoZq@8YK= z%%8f|pE7N&Rgsjk%BoH{g-R(&OGnS`6`N^GMWbn}+3E1TkB|I8;LEm4%Wn-^X!d&h zvm|=O&5fnwTM?3O43|+$x^xOWr);L;SfS$|9RAT7SH$lF*e;hR#m#TTJ{8oos5L!f zK$ljwvecu!1=mrX?KF!^4>w3xjhfwv^7a!HqE$>+>#g63J`Z?~;pNn(yzp(@pf$zy z_MfVFa1{jZN%aexYdZ$R09c!Xn?WVEk)DRj;75i&Alfwk7WjeS?-E(gp+%L<{vGjM zvq6)XrT)*CQn=d0x5*@YF>I)8HWP(7d%F7h15EvpgY?J#P@zeH3_)Xyd01{mP0K&%opKiP@WqEfs=9S`K2>6p* zvhe=6$v^s=i@gfuX?iTznJjEIDQw)tS}_qLZG7qC-`SJk_lfK$zW8zBKN@@^z3}WS zs_Gsflf_VYqRQsX2C_wyNVwInR_D&SyM)E|TUoUPP{t_2Jchi!BI6u~GF_r6lIn=G7Y}PSNeO%ip%%OgA#3`C!8t3aTZMI*t#sc)Rv3_=Tl- zJ3#T?rw@qycc5zXUD)X{Xubi|B)^ne$ii!z<^IZBy(THAFB}H>ZKJs{w8&W)Ir;1O8Y-V2LK)SWN-7m2QZy8UZXxjH^v2ab z$EJ-&_27h-Mz#*G3@XhdHbg#I<=GjcQa!&%_)YOA#a{}wEdxvVO1jG0>G#$*9yz{i z=u*PY2%}9N82WUHjT|4lMyzVaQk6<8nhq{9lp*`+$@1&W;}`a+ zrOR%W8Cs;PR_B#SxHou9-D#&7yC|sL=@k~$w0CWv&+o%6bKsxDp9tIhJJEbkb$@Xb zF?eglz9WXxMALP~)YWwRh-@YWZD!J*Nr-@?199@@V$vv*zf1lR_>;rlB#%n)PJIqzv04Rt(MVK0N)Kz7zaJxti-z(Jk$D z8SX8wwIKzg>5^aSI(@`<*0-&5X&iSJ_X~3bW_N^vaGqe9nO*9igFXe=_%m6a_QE@q zTdQeoyoogxzl19^a+#vI^W|l8R4M#7>`HP?k1B2|m#4VwEp z8KUKqm1gBDU8p#zUqrpu)Os|d%Xe$Pw7zC}ede4Y?z^kG-q%{_)#bChYE3PZ(LV;f z)Aap9!%aag*lE>z)GRf$Dx3@K?lJC@$>$UOYdqGMVSn$A|5vwYj>0lHOJ1 zR~GiRN|{(hb4KM++CeKKv}F8y;?IsZ+UJYBXYi8m!rG67?tCpamw9`sJ@j_dM+~vY zGFdb*+;2v>3|1SMRNKuHB#_L?cOJ_5)hs3p7m0Co780Mgblq5~JJh2_F^r`tCCyT- zBE8vK^0Jkku!dDywkHooG`+P&OWH;a!YxLm+vQP%e6WMQ*LJ&C*XU^U4?AJDx7_fM zWs+r(x0a_5BbH){amwLGI0B%P!{2KUbTs(pbp6?J9!o|Ga?t=Xgy$FleqGrZK!-Y@RVcz5|e7W zjEZE3OSMK_LPa2LiYP7KHu9wa9n!3TZa5o21Lyr)#Wp&$7m;{x!4|qak|Ei5s!4Vw zh9^=Ym95P2$19S`$dRObR24ZRb#Pke#Xk+jtj(xf3-1~0*HZ&|uL)Lbb22KxGvXae zMAM{bQY48Yu)UT@k~Ki9v;pVSc+vj{|p zt!*nTZb3o-1bnV##hJZ-X$&qZrUwmu6)DYE^p@CIf~rQT9&0 z5n}4N^C?w=RCap7N-?J^H=~=WWbV_IioQ3{{5xQh>-yfOEylLS-Wbiz>%(ajLv*si zX{D5{!vkMyy2S(JcrIJ?rM~D|p)wOWu?51Y9)otyrr{SR@ zX(y3W5;7{4_Q_wV7H5=R5ro5c2@kAkv{f;~WjFL#9%&y?d#ZQ=}#s=Yv zq8fMOT zA`D2uc_m2WNZ0QcW(ol6NUyZR@P0*3FY6SZCRdYnD^~V)=9KD5LKLM=5LcYN)SK*= zUz4rG8KmUBjFkwxMlgjwYuQ3E=5=E^N!kf%WS>{p;ypv)wXMCmlSJ`JySR@8TI#xK zfHDz~7VZ~{D33V;NTkTYz!(+8+%Qr z(BrS_&7bVk;>5$=MQ>^$buwIB-oTbV+h5K7<}rd-anAspU}|a~42GR;Z*Og_T3_oI z0!YoamvL`3gmNow2_@VPS{V@i_@pT4K@6h?qNfIMwOWz(Q>#L9Qi_Hix~UI_Ui8&! zbz+=u}7{5PxJ?0!gU9v{}MB$4m* zO-jXNJC;j}DPxZV8<;Z&1EA!O;ri4Tu`A(}`GY($DtN{?0aOfQoQ@BFU)Xs51>P8x z>K-Y3X4tYz1QE5@lB_>@hLstv1_;W>zaSIHQb(J3=k{UnuBjLHri*27uUx8>y_-ha zqH8RQSytrRf1$yCRh5ZGX=XSet_tVovmOV-)4%p+VeQgS_jsBTrxca{0Olf+l@#=R zzS0m+q^|Y$@SI0lNj!ED(@mw%LZYcFzxs1Fs!GpS$vHLEZrA3zTIZ%1oPcr9%gMlsRHErX?t$%8pkZW1qqnkkP(R@x(zSFdhOlXEuV*cM{y;im$){% z4zF<5%jC$}ki%x_u#%jE^8%z22sQC_vV3JJs#UO+qNR0pPNb8KpEHAnIddefE5+%e zZ8nkgw6XMNx#3!zxoq9%OQarbs@D4LbC>v|sbAk|W-F_hp6^`o9;102dt+GI z9WKVw$t~@gHAt0Vy|cIwk1f2y2082XPLbm{G&>IrT3KD$={FkuR>JDW#umEQHIK8z zE+&@eP?h95U7Ugzn&sh0&7j~7LzYd0D$x^!JL!}pdiq0OS}G2LD2 zcbdkjs~trlHiC6AL#RNInAA-yai+y+${OwbC*YqIXpm^On%9N=QFL_aC5}n&G)wpf zsU6HRB$4VCmzMEd+SsIyiyT^vFbUKPR7Yu+Hs!_Sn4e`uEInt<4{6B?H7_L8psjjq zSTzg9#mzaV8*3xp%5y4I>ej03(1PZLIJ%W#yjrOFlA38axg_t)Xv><;$@(AsB^n~Z zXRFy;onfT7xW1Oc%5Sh}%Fq)9r& zmhx28yce$6Poi2Z{#z-$@VL~L-rQnLx ztpEYmnEUyptd zxY8Q!b$xGAwYat@d@-fk%c6arXdrbT+E=^fypmHOUGg-_UGpntfUlpV)@Sid=rz9= zd_d7|q?x4CH4hBx8b*nv=`u4)mg?f$MgIVVj$M&D#WmR1(rJTA8cmE4eTjGf00jQl z8t%hY(>zzE>Jv?O5Y$#Dxza9gbcc!FCbm~gYiad2P>A-jx7pM@fyhgnT8f zTx(HUd|1`&ZnXP|qg!Ebp~fv|D(!J;eP=wWG!xr6j7=QTF66kknh!B#b{Np%%uN|o zsX~(GddgLOoVhKfp#7YoysYXdb4jaIadAlLpAhA9<&9iSoEx-#jA}k)+D*+XPA^a4 zx$>m_$19&Gd^q?O@y71{NxUuKt#9HH)3p%ycUp8$sn}`}UWB?!yN7=^Nln~SthcG= zeYItGZ?y>y;rhM%H_fJa2SxaY;jfL~597J;O_icdx>t&{B_1#E*10sP0(gH$)uN8u zRJgRemQx*-#Mc)WwzI9guw5ud4c~kY{g`|$@Zl_VDE03X>bkXzX5#K!?-AD~|1qqWno ztgbaZLVJxG>h0jW)GucHEyb3p8m+RK9zt3>CAO9Y6W~Gif*@D5 z{{Y(>P3EOCczWMZh+gUXZl$ZrTIw~_?3U)qQD&5_sA>nXPSYV2(CE zUd0?&nQI>iJR{>T6iat=;13JOYbHaFY(sX@SQPp($Zmn*n)3pslP0%fF z=l;pQiZ_OBN#Qn-&m1XpG*UcZ`I5oasYiEntlhq+VQFlOd#>A!BHm?%zq75(T4Zr0ix^(f;g9dF2KVAFyW)GF z8CkZTo)DKpnj2jYezD=78NoR6?o!WGv(_NfEY9Nyf;-9OA~;$=WL0L*EoyV4B`0L0 zoUYoBJd)*b<@aUnBBg#u%GyoYB$Df#YEBW8#B$V0IL%6=T`8%;qW5{K!V#RKIH{!K z?`b_>HW!Eg0Aas|wlSr;c$4Beu-ungddaD2@h+b)A>)eX(@VFX68wzONh^dX3T!*e zdzZuSgO}bIyS;dRBzUh?(`}_&So9rIEj8BO-ZB*nUEEknsZPv;0%W~F>9=SH<~-lU zPm3Nk_(!8@zAPRd(`Wd3YaNsLlv!L%d`n>WOtHyv9i@?sO1PS3ojz$}Wo)ViU85yQ%Qg=c+QhR9!zH}2BxUmuS8cA+a@)xL+Nmex zD1X^(Wac@v+c=(4XJ(dj$sv~K?C7u=W*`QT$%ICBRzEN#xCa>^< zl%nB@HjIEH#P;gDBgA<-1AqjqLNablf=C1m<$VQ0Ev2#n?=7W}La!rijH=795H>4r zeWa0vFO!k;ZowOtc9X(}Cs=Nwnnv=ZEh91w!~~Pg0aPi@c4w}6CbciE;GH0i=4A-z z@xJ^KBH@S3NDMgWP7hkflxsRtsQDu}#+9O^mD|x?O7TW~ol6 zwxu^D>PMMRmsfj3-&57XN^6;=%&*Fu=X67U_Y5bqP+s58hE<87M2<#aV%aH`mSj~= zGc0&uR4#ec)a_W9i`tnVZqUdal_cQhff!t1lfmoB&le#wMh5o^es%Lk31&M;V%-M- zWD|w~bI4i_tcvE&>=*MDm2MGou^vJ58yi=5QOE=kdK&4c8Z)KKTD4eIl%(U%qT$UZ zq@gsGo;CB(l7Ks5hbHTVRa?PhV=+!eKz}KMkwxKxwV$o>dNFZs0uDx)P`m@-e5;gvq`W3 zuRu`0)ua1NSN7gj$^h~ow5`p!&R1kJ1X&7UcVb6(JAh|y0P8MhmN-^BE6CO3Xo9@F z#@KZZt$@WhuH{yYWHAKccM!MNusTMHtGPyBqqgh}g>jrIJcFI5p*a1ei`;?sQAPnFr-ZRp1vjhclyB~lWLh1@0WDY(k~?X?!+JMzXClZ?}DSNC5f ze`^A&U3n_9?~Q&#fXZ>XfsbzH?l)wTah|#4FJo($SmF~wgSfM)3SkTj76kBHAaRW5 zyL-9f@|YAd9j9ur!UpUc*c@fOKN`iB7{Vl$lS@2hRzmZam6k$A_|e!l7X*dDz~dbS zbyKSd%_lhBMO$5Tz4W%a+U;qs_p#{GQgBL9o4bDZE47xkyLvlqd$#XupE`VYT{0hr zem#?4I+FNlJT*Vt=F-Va;S96eK_}VbD(KE$SiGW8paxyY2n^3=EzRGNw_O-e;pR>Qjx$Y(r#Ws;+ z0hVxJSUk;VPlzK;F2&gGC{PP>%m5i6S9jrCR)fL547E0L2DI>Zg>8sv-)Io%T6|n*!A)ur4w zb4w($O!315$7>;2$`=e!Z|zvWu#br?a@5Qyw3A9IQ1-BH>8rOD zbhW4d2?Z72Y(pzXe z91)s;X*zrPrN}JhNpMjx!#^_YRl^WKEy*}sp1JcT@f^y2@$3dj^&Y1jag6pHd&b@* zmpe-p0B#v!wC6nJw`?BZbB{{OSX=6?tMt?5{{RF0?lON0x?Pf9s_NR>-9O>|CT%7a z;U-CNOU9Qh&OG1Y-T${EsH~g45;hI8Aca61 zhZz74z=4zN+ZgFs-`n>L3ab)G9I^Y@KE&i>*SA`P>z6=-y+F@$20acBVZc2&6{7mW zYV&W+-LJ$_jBTV=uUjqt@4w_Mo*79=X%M*n=?X9aCjbBrJ^qK%v*z%qky%m$5I@8R zP!B?J$6ii9rfz?2%-e~W0y!kO3GcTgWZ<0Ru6qiZHEYO-c^%PYQWtP_SpmmQz$pY{ zI46J(Ip;+2O7@!ayqep|=-S^;xSmRTa`(NKwqJA8f0>p400_Ocs&0t{lPDyTqb;0} zGmH#XNx{Bd?)bUxi5zGuNYg~c!t+fO)ld>fGpSc_l}Z0ZE+Gh%jGzPg>X<4 zv=M>@aNo2a?Tw)PCZ7Aknia*St>c!`Cb)`Zc&_x_66w-NtmD)?qae7tNfBM_Eycv} zAwhEtYn*-`&G8>h*Su$_>V6?N2gaI~pl|hEZ&0|nOPjTpe?E4$x{%@|oxsG=NU0i< zH>o2(qi~-B<{8B*xrS)*IBX=S#&}O;ps^U1+@G~^s~5?IjAL$i!BnX^E=9=s-^piO zONGExh8GCv)voF|R_D8?M#+1L!bwWEHoUiLF-=Nb%awlq&G9?ot+ciRZE2=A^E@`_ zkT5BA8Y@L@dfV7q8<1Pbc>&+$$N>2>UpRb1_~+s;2hVw}>e|koqTAeGOJ(5=A{`m^ zjUnywBbp6<>KlZ(d*TaDlUvVc93n)B#O5Mj<4=ZP6Q_>k>H3G-ptQb{S2~^Mp=+sI z$r=dbx3Rjpyt$G80DK8Cv~0`rl`WOP^~<{*2U;m>9=~U#MlUV(8;vT~TWeS~JDVp- zl08=08asVT(ONZGW0%i{SVxy2DV49N!tjO%FRv$wg=|!16&Wh=jZbk&wy8x@aiu9* zFq?3c|o>n=pv9$}! z8_h23&3&=6sGbXXr?CliJhm(Ln>iqLk#|NJ!3!dY!zoY&enaZt96UGRXk_s}iZ6UC zt?D{tQ(4(s_ekFMYhg-A=pt>|O0M{1bw@8epNQUFFvtG-4`&-#~F3#h`9xd0b^bH!= z3rVHCl~UG5xO5N$7|gTY5-}P;l1Nj`DmDfq!p88PX9&iE%cUGdCf%asr#9SDf~2D- zQL9NtaaVlWrx@7uDd!j}k@lZjjHt;w-N%wKTJuU=$|}*-rqfQ%S?YbUulV!B6Wi$a zH@+!4P2Q<2vRKKbyiXO())AzaF_)S-z>jRev`zC7x8~x!SL1f4@WWpCUE*y^;HPE_!c zqm8L5bF@@%MiOt8#&sJ`X|8T~#!_2F%_&8%*+1A%_K)~ytZ4_}hk!3URx}R->GrW( z_>1BMS|*RFy{ObJZ1mfS+Sf$0g6?a%W`^1A=7pt*&NC@vn)~m>m){E}*W$AAY&vd< z;@i02Nwco ziSDD5;cttqwGRe-Pl`);Z*3>==BAtMZ*DCdJIfxIuEC_-T)Z(!GFZoQ7#NyCU)A=X z<4*znN%(iAFNW@XJL7)^_^Qe&v|F1g?DZWI<4=zX3*lNwLO@|KtZEC#ByS5Mv`(w% z_<_R^$a7^{juRFAmzYq6T3D4@rCGdl=Xj`Atx}Sr>bjPz8dCN@x}P*6ly4rM8qVtG zm_AoplEz`G$`xrwFryWPcJ_5CLNjyZQ1>S9Hz~r-N$D>HzxY!&pB|fk7m5wFm8|!c zjSRY6S6BX5_Km}7wvgT2`SS=Ng`g6x!(9ESZg`9)QIEyX_$iKub>QtMSJJO1w7G%} z0{ZgC>eWI+bz^X;ELRMwPnJw-cSZ>Evdh$re?W)88XTieeFIe2JU(r;8&+tv%e$kb zES8g_<}E4Rbj2b?Etq2=TjeAWas2*&!DABg*I3u|lN|7r@Z4H$w3EpJOQ^2VVuw&j ztsY42p}7am7S1D*2=@nx4+F^H=v1E(<* z<(0pQH2XbL3yJMDYxw7~yNz_2L`6}}vW8%wv2U3CQR7eeDL?HCcRbPfXm~@z+G||N z_82Dc<<;(|9-VH)SSF!$sA?BB65h{lk^cZ_J*|bTW@eMgiV##M&;I}#eku5O;$Mk8 zIj!g#ELvT@gYdWE{{VolZie-rTfFeKh18dNwDGnYF)X^j*&$g1xl2PKP>mZmh+SML zhYT8Ja^84MJ{Nga`BauF6awQI8OXq|=sbsn@|twxiOe$fUmJ;YtB6?Cs>YM8UbR@$ zg#^_YD8^7;($y+BO)8B_I(}1|XZZS)l^iZH(!)|wjX$e52T@a{2ugCQ;_6G8#(v^( zf|MU3X`OGy584Cb{{Y7*tu1~i_}=%#+BTPc75<;$;c294`V?BCq>;gUHLjPZSxbF! z0!uHFnvC~w!t5uCG@dAAkHsdqnp^i-CfK-b;qpKuXxokouOkB|1EA#7?r*|NA%R&` z5~{f*3}l8qa7hCvzvET(tBZS`Nlo0*G^|10AyZCO}NE2qa9+CvPn03dY6gb$z{`}h5<9jByz+zF<4u2?j(?;OAaI|06QN6yVs|F z$a)AWr`QPkg57AVtI*JZn@{)sY9`cHRyFMuKUB89wb(?)l#cdykt!22o(Qb7c)ca+%>WgdXBelJl zAGAwvCZQ|9W)nNXcPv4+LlVdF&&40wzfM)Rhr*xP-XXu5@ZHa-#WO``q~2Q)k*TvT z;#9aWteqV(y(tta9G5Yy(Z-@Uj@2T*e7V#Gvy4>ru|OC3`aO;?T;MZ*tHGg9S+Nu^G;TCwH4*Y4?aB^auZT+{n5BI68g z3~nnez`{6BtIg4tDsD5cIYQB#sX|IrsZ(xNh572+-+sS@4GpyFKqg-3tw1!J}*&vLJ9k`dl{{XcQitapPr^WFD#B*zU z6pL+ZCC&HQ^w!daytgyQsCn9aHj+tjCAeVd9a42w6C{faYM&nHx~`>f6nA&4Xp`Kj zc%Xt<=V1i0Dk4oJY|)v~Tlaw&s^E>>*3I42Z|2WDO0!$EY~MGVF2vkWB68ATxg!AZ zNK$sTKIL%UQBH+?JaYO97>QP^?Ili|t4dXxoAy;D4`~R}abC(QNkv{Zl5*zxDQEel z>(Q+7wRz}!I((6w)f$ne+;2E3@=4X_YOMKNn`&A#oPScazZh6}k{v@)@PCQzJW&)= zTI%-Z#n$fN&zPS70OnHLi|bCU`XrwZEg_+r- zNaX33ugkcHE&j#E(}ZPGSZdVV=+>I26)E#L&YM)432otINl1^E*iAq?G;W}&uFH;2|@Lp?;&UWUx z=`<)Ojb7l#b2^FEHg(#sZ0GmDEM*mT94V0iVnN@(Di^%C@lBSbhg7$`j^tg)hR@De zS#9UkSVk5C*&Cw_)>jcoRoGmUGW?|1lz(hY*NI~cX4n1^+v%gYj&tR^MR-h}atFW- z6ry0O9#tZd3g95;#k>iZWbT9Rr?6@BGq)U6q%e|imcm73LiuJ4D(x<8W^{c0%N%8zm~$GID5 z+>MmZROB4e+ME#og-t*SppK0L#AZpI%sMzYVT$*44uuCK*f@YLk(4o0K*{ zU?W#h!{rWFh57T4I6oF#_#d+D( zWU^^zw2Mu(yz{?(ZF6k5G0e-|m78-eG0}q@k-LG3r|}Bjt+YBmk8gFXTs(H~6|nN{ z)=5Z-XK3XUg;gicWgB*oMn(mGsY?#|l;bQ!pp#BjCj}iZCpYe>wA*W)JMyHZZCUx1 zO6uH=P*QK1C`L`Dz10Y$?weZMWbbFt?sSc6!bXZcMi*HS6EuHl-v|I=IRx@Xjq?)D z@%eld02T~N^tRf9M=6%tV{r!Y<>Zu%s;aI+hG0hEMl+HIa0$g=S?M;qWYJsrgHN`( zySqqQ7>&_Xc3|YPh}jIIf~=X_5W^6640_6VehD;ozp%BjM7G)noU$V#?d785_s1+t z7g;z~9lG;WtwWi@73wzRqTjmXccM!0*}JQ>?C)((h*7D_8BUEfxp|U&%3P^l@=ABn zYP+r0w>eR(JQo)2EDNYa&4y^>c_NXcIb?9n6Dkl0kd+&Tc8rl-ewiz3TiV#gW`bpj zZ6qc+rDj$j!5B#pMo8G9rVL2I05CP=c6zYMW2Z+g@x_c+SOZ0GOTw&vIBr_i9W?DHcgWJxD@eawm7eQ;TiH4_ z<<_9KcNVh4dhi>OWpx;Vjhf3W4RXbZghui~DyS1Qj2CfL1XkQ$9MsWb`D21RiI(2c zHi=BK$U?;mg>pkP?NHCP269*m>}@_OX!_5G?pkdlPSrd?63c3B?+HLvB$183+97zZ zU@O0Gm*z8{xQl*R+t`DIHah-6LJA220VhfsL~uqp^O z=^9sx?e$2E+INW@TkdG>?rmjTxSh}sG9$Y!=Ee&C?aO0!Nx-S?G*;GbZf-6$3zxZe zUCnZ1MVn|F6(NZuRCgFJ!x9MQqB#1EP1LeWUvW*e-s_f4trx3WXqy|s!ZM1D+kejD zv|e#Z-S)D+n)EoM2EPQ+%MIGk60emO=)jDJ`2ZVOx0o}92PC#Q!J_4Fr)a~b6 zFJK!>XM#6m5rT3?20iQB?0hk(+rbkCjs}ilDnzzc_em)Z3{tww6Udn$W6N|3NFZbi z)w%GT_Yd~jw7UsznN_~iZjxJhr;y~^#~?*0Hm(>EmM0m;F#7yCuP8@FWhnBeWwrdB z?(FY8WYeA}f(b2=T?&>(lc&)xmmMt!qyKkzt=Fq|>$V;~aN2 zPsEaVi$K!vF5$nkwurQA1h*31v4xnj`Bw2;-NN(Ew z)HTR7AGV7nDG0G^k{qPd+z^LQhS(hao;dGgc3iZQNE`u#s#U2MFWt!}XwAw?nooE} z^7p3iYbCYiqDIlDP7XJe<0oe*r5mK4lF=lR=-acpkHpVyx3jW`%CoxjLntn?DDvJ# zL}Qk9X5K--Er3TjjIjXp`eQ>is$JSU&u+z|iIqglAjw_r<^+Agk(A{?7|A4&pNqU& z{vzp6G*oQYcH*6vck@1vNT-+gQCq;qHfQ;jA&@pnKRJ+KdIVFS%+{5( zzGH~B6r0OGyPDT5@XUosWhE7Yvka5nTaa=wT6P!K3jq_Lxpm2nC59s-5KqjqM;b9+ z;B`K=JQvoiueVN>RQ~WbT~V@mBd%S6Bm#5Sj?_-IPkJtttgMuiOJ1!zrk>8}U37O8 zX~o*jYkQ`hn^$Q*mhyX|duxS`DWHwrZCh%^Zt?F3s6zxY{Dn_mcAWIfR_t2KJoeL1 z6}+hd7>XtlkiaZx(=kO?WK>)(IO<6zq0=qwu9QqCyR>fUbppM+W1fLyZOg$QKO;Ry z6&=K7B$gu`mE1eBCWsiAf&m#tZ0DS3IU}WT&TyQi7NvE~cJ8&3QI)RkCu=*YUwuvE z9#p?XwodD<(puRyWOjBQEs`c5W|m8LGcZ8%iDFA~#P56}uy$X+8Y?Jc^2kRg({8*{ z>1fbt=Fd~Koe-$GXNoxjl=FVn8aYfZjK$HR^LL;ljzxUhuv+ zuIzOK>)$>0;JG%YD8#oY2@J8yODpG`6(b}lA9o-SPaSi?iNMmSC`v0;cH-il-mN>v zPD!qstt8XFjdWA5QYuTnmrl(mqupA~Zmo8-UVhW6>5+J*1%}H@SlJ;9DndNlX=V|x z@2xill}X4_HW45I<~)$T53KwbhgQC5AHrfreC>H$K{Ctya!S%Lz$6jEmO01=ocFeR zrl6iww)gjNymKU~kxVUO{o7|}?$u>T*pHc3MH_l!lU-%6iSO>EmV5Vm=}2hHM<9`R zJAj$k1BF6DtcA;9Ws5f>iVqip=X50rM(y&s)pCrJ)9obI{{U-6Wv=G)_EpqlQ8g_S zYBA+;`y1Z0^S;E-du~3j7b9tt111vjFGxvrX3|d8J#RBaS%K zMIFp?JIN{BS;6xH2vh*1n90cpcVnS%t7+PZ0c5dRgFI(_pg_e~f}pY5`%Y9aQJfM% z#X6bhJ_<^7m7=dHL*I|QuCAvEKPPE4ozvH63T%&;r6fNEeFJMUFo*k4~YD`xMaK1wOvAeGS)&`;#jQYX)P`i6uHZ~CfSO~ z6llAFGB5Ps;!P_@@g9q-_-|a%^xa!P)vWF;wJRByb-eJ(jI8KYgTZxfaXq!fOtV{D zM;y_*%Nnr!&GA3{6RSs`R_*iC`;K{HM^4bYnl^QT-UOmj_D~x^sw%(8Ok)V zRq0cy9!jb+Z8f#6B-4w$v~62g9bL^If}bCu_?nuxg(dJ)cxzbj_Ma5D))4Ae`mT`_ z%+e{fh0@yGq{@hw4Ih--BAz|Z<`z}<_;h;-F!E^dTrnkpxr8_jPC!tuxd7wu1A+Nh zhI}&pmOOv(Q^bBC)HLrD!>?HC^GSDnxB3dJKiXp$@-=Na?4oHSaOopFGG;YEM&QhT zpV92~zq7ZLl2se0Cn!sm-S2&!_1E57Z@%MfY~@u7mR5G@(*V3{jA1}PjGzv4(;Qa9_*UNj zB9|80ad})7h~3CUhCFSN*dmk**9xTIV+V@0Ev}(v&2tu!dwT*dWLsd&nFi}Y+`I=29y|wv$`}QNA%1d?%vci(WxpuZ9QdL3D#AFW07p^k+KXml0nPbr} zzj>Y4XK`~0SXl~SF)_0bnX`~E8#&16YtZytd7gPCy0^7Rj!mkDLwP1X_n6yqo4SNR zyN4L(C&vCH{5QAME{BM;YpHY{S__EexM$RFV$-gp0zl!QTap!aA!&NQ)8-$UP^*nkKEMTSs{=t3BLz5EAnUt=v3ql`69sND0)J05>BHF~)`D z_OUOR_xADr{ZXR23Ix7m1Xxn#)QIP1WmuX(%JOXtry{zeQO2Wu?I@(3llNLq_p;UB zN2}9EXP`zZQRU^lp4WTc+V7%kRex2v;(DLM-x6D@YySWZyiIwbc#6{M2^&t-WNY6K z>K2b8{kGcv5Qcky-6&`#iKJza1!zjPSLW~9_u#+8t$$R|z9aY-!2TN7B>u;S>o;NyG-PNY8BhPl; zY?C-y?_q)|;b~;_87|oo zOI%pHvn#R4X(9;C8U5Q56ak#-LlG&$q!Q*%7MyJ<#_6lYxbrAUMxFSB?G2S+#pMpY!9V_@h?Tnr%N@y_3QhP^Hbf=o)R5&8S%1 zeU?!SGEILLo8-w2$cegmf_6S_`SBabvBmI z{)hs+EhN~ug<_R~D>0CTVdg9qYBT4kBkqE#f)O}n|LWfvyjHT{_5 za5ZTnWIaK1KZBvVjeAi91t-PgqHzjA%=<~m{aWtHqB4ZO}y$#Elvvfr1Vk?gSi`e3m06uq&Fo^Ux#1ac>Hdx66tnJhJu6$kRN5 zImp5)^y4DEOf?T??@siSx=J&$OIK-fq@KFz8-8!guUXYi)cxyv%2Hg-yIS{?=JLC3 z=(`>lZDW0-U2KV&(N5M;3201h@|^C75Zg}&X#)iE1$GHz9m0#G4-2Ldo69O1KsRR~ zCNeSzBNz+wdUTiHZj;L`BY8X>t7~o>a2Oe3512{kfZ!ba)_jrQy2!HK%q`hS`z$ul zjz=m?hBj;roM3`?FeKxTN0GM~DWxkbyYKR8C-`V^DJb497mIGm{g-R2Htv?%CGy;| zfu^&2Y4*HZ56VDtWNh}x;2)X&H(+NR`KGPm+hZw?(#jiV4$>EaHkOd&mt)ks5=lIA zPp%H_#23pVc~jj*5|SPARf6s(o-w-|1B~My)zI7ccUruLIUtI5GHmkqD>SSL7;-Q- zBk%!S5D#4Z!$>cy$<5YQmv_pqX5U*j^}W`lO{(^XvX?Sl6M8O-OX~IhwDOxfi zN{HM$Z!zqCtpZ7gBcgO`^J56oV1OL90d+k?5tH7yD$=J`PE$=a z7Ng1T*-F~z+f7+$ypGy+rAjWGb>@7}nI`YDvS}o&-$!fPwXp|^qO#O2Y;}fxHVI== zFLpF-F@WuYC7D!3HO3}(i3&m#D-v5H9+`3Ct83XU^ouP^P}4PwSnTdB^?BlmMX71T zE6-`c-uQ$(k1NCT{yU7U%&6$AOyi<%GoOqYq^mDK2P# z6{$%#A9cnpb44`f?9=z0tarl|MLk?+biLVK!F#q(X8OGq{#v8b+ghH=-4(S-ue8Up zgGbb~Mpn7Jwv8hYMR%u5ZlRE3v$>Syp|6bK>!iKW8{Jgqe4*~lru0=$g0LL zbGRJj=Q$*r)o+P2M4uu{8QQV#-a~>qF~9_Y-*!nqTIH#h*OYmFuPI+v*amWt7LR(<5P*HxlcO2^T*H#+3kLGCnLEj0vwL~`Bg?R+^_ z^NK?qqzn7}$FZHsPb7St){A&LE67dEI+dQ6s+RyvjWxxojZO)=vU3tmCcp|w9I!Gm z$<2JoJ}OKUWVD5FQ60b_o=b~wnlX(#c{^Ej_nU1uy4$(lvx+S^$;wN!(`z)|it@TiH2(kt>m3uptz`zC z4d%C{YaiJcqV~f5bi=1=Hq6TKT*Kzas9!9xTv^R=Z7MWk8APRoF|bxme-ivX@JEZa zzxYV?jZ;|g_4>ta9QXbf)MC@uRkpS)VYk-pE^O}Y?&F1t!i7!h?enP>@z4A$eO^PB zzm_kR{%HTg9Mj^rORT};4WBAIrKfC(D_3H13x4!NycZ-`d}jn_C* zc~xaBqqzmLa^1nm#(R-oE+d68Gj7%DJ#X;6Juh_Ky4(H+($48l&QOY#tlu@a(#fY5 zmAY+rvHG6=HSh)A7%Em)~j^Z`m3)- zL(Ql+erYD}7Nc6FoOagL5_)NCTdz~~bv`5M3ZTVt5Rbpk2SLy-4*=shJY%6F2KszK zu#pQT+$^U60{O}9>Bt;(z~h|oKPBS$v9-vKdzZ#JX+R9zgMa|XK7*X+8O2OKD{4DJ zCG3&qvI07WP&ps#1LTrOIT+wz43k{%fpP7%?drvEcA8Gz8duSGu@c7Rk5@vQ*L3dN z^>^)xI7{HD>Q^TDrQv&tEWDyuG(UOyC=}LFgu$3vQLRuDy2rD zGZDyNGjSf^Hc08*o_q6Ar^PFWMtx@@NP27*qLb6 zzjtfw^=?g|Sd0Q|+?0ChKD~Bp@B5F{CGj?kxTgDZ#O({eaody7@;x~i9Mq%4S~<@U z5V_7+alqvC_Qp8C{14@r_^YWppDzALO9RT0ybwDE2Lsd+dhl{8Klodkx|5x3q5+Mp zQJwNSl`Fx>#!vO3aCTtZ<*Ur?ue&??S~vVO{6_H^a^Kn|z13EiYy3;|KUB`Yq_U16 z!8<|Rq+lEql6gMdcKXsCYf5D}5bgBbI48D7KSA%;n*6E%0ENk^C{Q(PmvAsqN-`Ye zjG~|*IlvrLOYxV)2uGEFEL)3i5=hb(`ABVu%mVz!Il<%TD_HPmYV4G$tF7nl z7w32QTfU_IXDwS!wfdz|%k@65{kb)*6#mP95aTexIlH;=t%}DXS4J~0FVZA^nRJE_-flp((T`2dujQFFe>t70P zbV>CWmJ8n$cwv6dt{tV4EkURGh6(D0xc=ZAfnKtHFZhhg(XG^*5d>@JTuB>7up*+7 z<-B3IP{1;r4lo7q9l$+T{_MRPH zgRhR3787--(fY+lP8I7$FvL_;`P?GvLX`;0ag1jr2u4zrV-+6r{t88|XzSqb09x2W zqFHsD>$wWZr1?;3_sB^qNl+Qo@~3edPBWVIzt|@0!ccz8-UPVR3=z+Fd*TbHQsa9T zyhyXN2Ly5pX}e` z&+HF^ego5lo?As}sLsT@suM1wJ_@K{ysGoYd-Iz2YVh7AaK;}ijc?!4%ss7H!Vc1l zjd>`f-PO6G@2}!{@x{@3lY=dN61p5Mx={j0!pF^w%#ba*?7P=FqrUpQt1f-o`YO@3&n#ey&v{o~J4&Nh;N zhYSxn?lHj}ahj{C{C0;%ia96Lu2?*&62)xEG=t1MO3|u}N8Ioazc{Z3937cS^1`KQ zN$8V=zV*wkyJoe9Y#0r!E=Jv#N{HTj^w94*}ujVaz-lu0Mz{5D|6II>3&H?dG3>vSGJAorurE? zR$D9n`n!5NJY837tLmdt>H4emvHE}qSBJ1st0sId==>GtOlfuU* z?0RgUu zLU>a^l34XG7h2iPXA9lj+s$_q+<7sL&ZZB(-EgR-7`D-#OzZfYeL}yNVANvZnMYVw!NGhW$lN7zSV!LTwBX+2DvJ= zy`G&rZ;5A$-d2@vUNi|bau+a}5APy%1y8I001)FojOfvR(o(A!&gyWKDJeB|T37wt z;^leMcb%8Irq-N`ILSSn=Bm_64aeS{erdIRX~&(psanyJvRXH5pR?XH@y>&#cpJuA zww%5n)3qHx!+ON}UGA)4w$rV(bQ_67Jg)HS@vnP+0B?!)h zYWoT_qj;#-t54d-Rc74f8eY$rmNHc(Cn&Fq&$x=6YP4Qk^}IYN^K-XaYue6BmENDV zlqDF(_U6AcZt+%4UTs%U@ixDCsB2op`g%#JUg}z&v|4#CE;SqLxv#H8D={QZJEQ=bu1OlC@c+*bPl2!XK)fRaCsO7nIKoLRMBz>&pi9EJ_xKg2jAlI5}TArak z!*hPq1;|uL;esV*X5A@B<6ZK(Cwz`so7XkQ!8*sN8FdK-^}K5#hSEaO!qVdk(*$)a zpc8(Ge}}4yQBg@PPlTzBsTn?7w<)(e zlXq>qw%mE7lGWZ;l%(X{_DkC|KNstNZMC08((bLINz!YdGUd}wWI#lpXAF<#955$w zj~hl0Qa*r};_jP1n|AAPE${x!_UrbNqE~SrmRcyInd6aFh5>7sS%BO?&3s8eiM1Q1 z+dcKvc9Ee-wEa3rtzbkQHwB2X02~ruEzq2bpq?bt$tx;6TL4%}{Oj_74AOau;IkaF zFA6&WQ&%jfR?=`u#c9cQ?W26$-xJfOi_9qIQ>2>bZB4fMnn`JE#YL-IrQP0***hOn zUwlrt)-)+}E6YoHSQU~jZPjCz)m67MM{KPB0PB9?V|2_F$tcI=K6G_G64u&z9d31* z=WUQ%gm|sdw&2L}F>|*#%A$1u_cg#+J*DZjfV(kbe|%*r5RjuQvm%fkFiQk*R2&rm zj8@e5A7ZvPqH#XSnnk&Y!?eUzR3KQ;1tFF9XE{t(Au4L|kn=;f_^QFvfAUMPh5F>qOL{h8AYC zyGM0Ff{!5?U{?ern|EcGZcZ{VNU4qvlxoVXVMp8Q+~ox1v}sxEB+|ONl5ba~$1GJx zO+s?3?6giQO+neGcOQkO?QI&px3!IHyURgyacOxpcM?H?D28IuDP;$0x9-VY5;7Ek zMMWLmoHpV+aFIm_Az}mp8kakqsXK^lmNIY-dmM`Mjau?qZeW(y$Ner*wm}dpwIgGL zIbYp_^Acan1oUj}&2GbQaV4m@@}incTV`qH-ocqdmT2&ds@VCHYbyY9LgKqs3&t+( zU27ZKDZ5>z(_7llXJeLC)#VnWf3o+JNm|cN)_Sg;PdxD+u@Tf|X#tTER*p6(&k&Ey z0Hby+PTXgLdE=V;^Y(Q8tG+LM8q(v@bc^)Wdb@CS`_Otf87pY6wm(?)ulOl1#W8hmJ{((} z4&7rzG}`UtnvKc3ZY7Bzh{X!Pl4K;`XlIxW#u&-kK7IYGJ}!8#;=jTl3i#vV4yc-! zi8a{cg7V@xj43KbG$!5%;@>G)(jxnQa&S1~IQY8N($)~d>fz_}i>z4&5XFma$OP?N zfWy=tgx9cqaFL++1@M|FBx#JXX{^8?8w{!j{&GQLK<9&;U>p(gS++ry<<)X}m^=<1 zg=yy0sk-#(#aER-tKw=(oT}TMsY)|}B9#A0gHgfJCksY*}T^Lt7$ zQc+3AnJG)&*L^nA%%Y#{OAMCkv&PmC1dc*e8{>?)5A$X46mB43C;*+@Lb|2Vo@AEA zVv0NwBFtGXBPa-EA~CW=$ypJGA8BC!05&U=zST$(!*0rBNFY{pAnjuq`3M~tAH9&r zk=Ot%SxDrAeQ?2LT%xOPR17{$s_iF?F%C~05=DL7aJ;EXS8XMGEo_#HZC#U1>3+Aq zpDOW6O~y90rHDbEa3r_Bf*b&B&Z+}fruCeng2C#u*rSxsjUm?gK7Pb}}ha22k=z=YTpX)tmTXIa}R!gK1m4 zOM5P-Jn2HoN^y<#yP8sOvW@S%Yqq*|DnPMKZ#0^Nqa@236mKw=Fsh8p!l(@*or%r2V3|ER$aCw)d0Kw{BlFnzgQT{uaFP4y%8AdEy(pnQZ2nRy|7bjFQ|mN)|<# z5IlTMPPD?~F&e6`?FG0^vG*);e zwDXLl+-_LXEDzqwM*y)uD)rCGNCT%@?WTfnJ#PenM3(YfwY-WMeAkjG7UTxV-l-GB zpygOd+#2&OV*1-m)*@j6gsb_%itn{~n<^v`5wnhW4D1I4D&*&7Csq=Qi&BhIQo48i zmzUyX)M?HQ$u!;N6q-@e_LcAVZPUHAA)eye@))0b8)=s0MhQZXzkbm8W!hH-923+M zy+wUh;XO+K08;+WxVBi6M7_6>?c8B~{;U69?uC+wbi? zCf`tkHA$_JgyjGYD#E2VZaD=VS9v(X$aD`doFxZ+gr#f`yRl#CkvZ$rWB;u6g zOW$#*+fk;Xx%rpqyaSGZ+e-^K2vM&>r0Pa;j1;9pKGvI$G+LG8Dc&5^mnSrwpC>8w z4vpeOwY7&zoz1e@O?oDg#_M~_Yk_RZ6nJ9NlOzNk;vtYa?5K5pSH!pad+I(MzKc%O ztfZEGKH^EX{_5s;c`fx5v5nQRxOpam5fYUwtG@$r<)wx=?xu(=jFN6p(}9>@(>p*6 znK&vG5ZT+7B;uo7yk^yA@^*R2B0D$lV~$5LxNXDlC;@N)R~W$}zYM}>SgbQ}oTWN; z{o-$1sPf)3l5$CMrO29%?R2fD>^PjG4~b5sRADQ*MWp$8F6QFn7j0Y8_mz@Kv}GTP z8oHSy)$Ll&XeEy3c$iw1sAZ`W>amm-dLJ<(S8S52ufa9u@Iw%c-rz zsebl@%u<#<7r+vqPUSvbv(7Tskt! z09OYX-Wi+Sqm6T>>r%u+5fvy#q$L*_)2k@d!s=NF-SmUfyXC$1TJJ ziDO8ZtL-~W0h;=!;fKUFx3!B;)$eWo%Ogc|XL!%G7@!e|Zw}zlOo0N24!f{0pkP-<6quXyV=Sk~#kXNgVOd1D?W)`)&UKW-kWL?>lMQq-`@a ztr*qh#BCuiP-GK@B&f+J1CmcPP_i6TN&84@lm0xqr2hby%$J^FQ?=!$pTT`TXOj4P zK(yENT|-nCR|inj5tC$t5*8{XSb!(Yk>poi2JB~X05(h>7Kc{QwWqqUvANN0=CXNj zb->Ws!9A%SXO@IKcNZ-31vp6D0CI2vu0O&aDLxaBHkT~gwwPQ?e+%uJ=1d)hgR20| z9B7KDQA4V(;;cv=_lo>U7mBT{9?bobV~L}dH(i00@Sz+q5X`HEUD3LO>TC5`R>V`4 zN>NIs3fFLReCmuKV}B^f@^g>E4|h^RIqiew?7=Yc58cvsQaqE>@n`y1s-|qZ&NC z{_ND$uAAmoT1xACyGP3%}N z%t`8D(_crE`$s^(@dLrBPaV0vhW(}f&xS$vXzrhU<#3ypR9O#{94N@^UTl0vZK%Tb zNojJM@bX6Nh%yyhfLJ3Qa6WY-oR0O_=$fo>*~6nnaF&P+R~YPS9FwJ?I_Eik*9af_PyncH3Wc3uCp0!CjR5j+UDBk_RC`GJtW+>Gf3GAR1gh% zpN70`txu{ogfF64O>GiK=W8415tcy4N%lo6mU2tR;Yc8>G3#G6+jx^%wLjT^+7fDd zQm~o}3*rorN(oOg8->Qef!HdT$UCrDXCgGv&GxLCoD*Kfe2uy^6P1oeJgUf{iDg5; z9Wm77isk;zqN&a`B^7lpTFExm{skzuxnFd-qMyUNH+cH9lw}m%oOz(%DrrA^RTkey zz87U@X45|A(e=$rO;1dc52Bli!}M}QGBT^h3hP`D-c77L0N+-QmS@k7dOQblrZpkW#N zq%1xCdY@-%zZCoz1Np;Sv}?5Cv_W0EOA^v z{4UQCc!5o?g>*?)KP9DoLr{ffxZ1IqSX$bskWC=kLXf6K>VPm6=bH3?3~Sy7@GZ`dCA3#QEx3EPxLryDk;SG$ z(-`Ekn%U0q>1`y6gqIVt{{YK9*;)2DI&f|jF&L_`(h#XiT&>#rsM)}HcIy0{wFmvJ)Q#`4W< z;6pxILt^nh**wWSrrZ?)%55DlitMkg^itY=+*ewDpxS{=HPGC%+>_!~;`Hnrjn66;WoXsurE;dP=Rv7Q^Y26-b9G~iEdEO5kw$|hep zeZq%zzYY9y@JEX^3!MeqQ;SfI#iUZ*+C8<9^9d@pvJhOB-@DB66-i)AZQ{Jj(8Nlw zv{dT2(NyI%Djv;3oTVwoDk-%6o$VTt_xV>VinB*mIZ=!`dFiJ&C@WNRa+FeB(r)(V zvTiQX*(UFECtrLZB~6nbxY~z`z?eXayI*D6 zpB0Ln+q_Y$5pwgscZCrU3onnD)2oSm@ug~UZrT|z{S7B*X_c;SNL z=1|S{Vo@`aF)SRXM#0I9;T1meC= zgW$G;`dEoPORHNYmhiVtXBDi_NQxnds>OA1*Gd{N%PUC%U~)od71HTCSH(XKLuqJk zw2v6+HWFJw4at&iD_b@#BxqXV&HmeOB=)xDywEQ~u~N##h*QT+;+5&v=21^cI$Yap zs*-ST*6&;B-O8-6(*5NbLiXlx=CzZ(`C3X^_Et%0bKlnb%6U@89eNA9w2;WGUh%D) zV|?UGG7DoO{Gj=6Kn;xY0qJaRFQmSlq8(h@#IJJ}=|nL=!{umYlr5o5|yoIL6g@v4;DKOm0MuasfGIBPVu9%re^QHwhE8am@^J zg)AW}<=i0M<+v+_kral(=N$SPnYA4jT_S4<<-fDJZ#2hoY>~G4Hn-WC*_bd9N@I2k z2yLg3PAkdRPVu&pqTRuv>iSQJZ|A%FL{^v6-088(xnSzkc{e$np;A6oQd1j%HRscs za+DMu8AhaGA8y~XoLXtlHJ>t%F0Rt$Nod}>bV)Rma#LKgZBzK7)$JZcz2^Ly^gX7{ zuFFV%(4))4Pq3>ToP572BXJ+W!vI0YIj*Y4-o@ttG*L=&%`~ye9Al1EUDSNcdoD{K z*UNq%>Nm}!YId5%qv?JlSfr3y&KBY&kwFO2T`P#^M<6_T^2(zGBOsHaHBDJcx1K>5 zC3c0u_RAb&`Svx(Qd6BwMJvWGlTf@`ahjAAl;YLnI5zC0uN`f3qA^^snr*2j?W$>} z)tYu`t7~+6n!It&$^t~uZQF4j>PGHZk+}qNhtEKAH*=3#t#e^5%*`@hD@b_;N!QHD z;O?29ciseY+3ZJZ;G))bHf8f3RtmwxI94UGfwXL1dh$pEgU)!C9Yb7ct|Yo>9^K{! z*=@&{JaFtl-hNIbm&{ol6$mz!TxCmFBZT7luCAkJ@XGq^udVLew=z~wt&P)*NiDlw zugiV9f5Y}rcy{e%SB~=X*@;JHOQvDGkQsrBLc%gmKtIFA0LZI{MiH|`adGFVM=0!A zlEmeTvw(0hou}^{wh69a>en{$%<(kRl!`}4{#9w+V=j=WG8IE3C`ByTQbtJw70CF{ z;vL6_d?!Ao6w*VjU3pfP7LRV%O%2q=-K2QpV#O`uh4)B8#vRaZHR2qT07zT3>N?ib_qZUheXHdUGr2wDY%J`-oxIV7l7`3@js*gq9hVE&}XUEI?r_ zV6kAOK#z}^fel=Sqwxd7a5R!?PkAlh+6)gG?3QL+k>0d^_{kL)HMsK9_lqYX=b>xNQNXW$c#LBJm6z(dKhfG6N-&Wk*!LSrzIIi-@S5|Jd$#h zAsTL6ua^Axy3t)p;a3w%lTnlX|1f$mLZ75 z5!^`=$be;4l^H^S2Nn6x@W;oRm8XbbL9(*F)nmH7YbVqa8@)E(KeLuAb8T~XY#rF0 z=wfJ54+Kg;8T#5!5_r&Q*S6XhilfmrXiU%cO;+3OZ8T~RmJqGPA~Pz07G-8CFvcQD zQ|DL0W|&IOm1;1fPF%BwBD$JNEvU*>VNFg@P46dk?we6g=Je}fD?v`3PiZK-I8(H} z>pdXk(r?LGwtAvyx|A17I>97zLm>m~@EeIO<>VOMRb6wOsUZBdS5)xg>cNfcU3{(P z7#a|W><2Hi066(_ROIAv3F-3{&F9DO3);7e{8i#jI{yGi+Z4A$N^6Pc(^lq0K_$(! zu-g+FJc=H0#3B;xyA+Y^KMwvPw!18FYkJ<7J+$zsH$q9Exrh+PIhBMG?qFG#X!idA z6l5_Ou53;*;UufZz817;-8#5xyv`~uDMk@=?>Sw*SjDE-!tblvmLJ82qIvN~0N>^X2m!$$3emi? zvbA9hrrB+$DvJZj46(|sjfm*X+1_v$%o#3JE=dBqTU`>gzeh+C+v4NtSxUAIql!~izTsv9uejRxI*$sB#0lX40&b-RH`t=AzWOB_-_M_t7@fR#Lh&r-YksFL*vwlv{C0wAV7WHftV6IeT5Np%_0I=>t$d4rPzA_qHU;`-xg#@rd zeq1QrNgIhg0BhT5scIH8Bu{g8`3o^HxngjM8U-Xa0)U@5Bo+jQz}h(46%w>#&#Q#g zljUtY$!UF-zV)4~)`vuB)?aD3+m)o6=8xHnv)7l;Z$k=wHEpaU7A$Pxn5UdVMlP?4 z{HpgLeDX%*?+P~|01!wO&98)n^BcLRoA;!YSV=$vV=7)e6$f$1$XtLriuC9ce3)pG zctW&l;I>17w1(ObD1J~dFu6JGZZ(;o_bU_aGHqo<+RGZQLn|>*$++@1E2j0?UEfr!x;t5Dg(@7$U0TY@E2CF?D|h{So|;|q{E#=Et+kyQ{ZA+!77>LtRdBn3vwsT>{xo)mCv*~fxkP{|WLtfzQs zCql?D>=SO&l~+xzlDLmMa@$EXXYdFBhr5PH{uNmp4YwIq#AKi&p*(gt&2JoaC8s*( zR=QDly|ur8R^Q1Oye(F*%cIeI%T?vKrpa~JbLY#S4;ND)og_JIq>J-5an24;IO=hn zV4ek2{{Vy^P`U_V(;8HNxhlp4Lz9;$00m#D9C4C)`bsYXmR~YEb<8Y<3qPB^h+;zk zip4Uy7*m1L)3gXPTH@d6{6KS}L(h0ou zPveX;#<7axbVa`9%I|JqWzu%M2%;?(I@#z zy9QAxn7~KMxs1ox3=LsC=iW|Ls<_8x2|6*poASlUrROhIz4eY=WZI`rE?PG@`$uJ? z)w@UJwYqv<$H~^#c3N=VW8s)&kb*?Fc1trk;EXiNT_2tqM&bbWt+tEB_t2~kPKjvh z_>w~L1&g{zXn?v&$iNYTPdz!WpMVoxD)N2LBT-M(WG@!Y3(YV?6c1^u|=zP~FhUbZhH+T2$sLIAT%qb$V$Yy_)y5I(H zn>{<$B)TMMLlF#8DRJf8&bKoL1pV->C>Y?VW1ezACcclj@U-qqH_E5(M;2Gvcd^eP zX8-~YNhD!G<*)QRO*n|;wrQs)?#7$R9SL{$#t8#Faw~dyq-5-;9afx{Z_4&+DSWi_ zIj4n7TRS&xZmidvZQon(@;n1k(){Tp^KNc_U7=buaJe5dMwtWUJPdTle@=SiPJ{+m zi%@3RLflI!$_(=ycyom$WyS~a=cRjn{*$QA=gYNAIG7$tIAFsAFSM~`<0H!h)xCLX z{2P04?JUN52P#4-RXD*dy_s7W#xWT<80QANspd42PE}%`M5Mg5(OUOT>g%n}N#W%0 z%NF(4_tkg1Y1`%VXN*l@}#?)wKlA!cYQR!Pdh7l>R~J-y2jdT+t1HV%Ws+B(`mN~*f78t zgNYRtay>Vo9QWksuhytZr_P0UDydFa11t`5TaZB+=n3Z;>P>r`z8;ywGbtTDU707Z z1EI+2`ukQ~z8h%swgOoH027i3QU*8*$Dd$FAXh@np{4E9XZO7?{b-4JSuIlgl6qUR zvpiv~<^*AJfJw*72|Qyx@DBsNdGA#u5^m?9zzS4nr>X1T2h@z7)$9ktbI1WO$;kzF zCIHV(%;j(}GDg$W*R5GRDr0gT0={xQv@$jTBj!IS&U2nlI)POjZ7Dak`YWxT{mFD@ zmF(@Z=y@`=$0HAp0)e>X9th7*UOIQ;m_x2u?k6W5K|N1ieM#(I0yt9d$&!wNBgqa^(ZUO3Nj(D7Z2o*R*VRZQmq2+^cD zJ+p=9fs%Ol?rKfpyM+YF8--Jhk-=_9AP)UFKVLy=r73T3nnrFl64AZ=E%#jHUiwYn zGq~%(%8Y<;Fgl$5-n``YrhjS3I9S}0I*f+M&NA7_?}5k}>~WrgO$tOKYOy_Yv<zl+2PJ_el!MeZbF^okG05X5ntYZk83cmg-`&$5$`2lgEDzVM zQj#W*?ydnpE)-O%=6Yjmj}YA~ z&g`K4svN1wUw9bd4ayT5$xDNB;m;< zf~-IwdJs1dTY_^@8`mQeNg*5!r9nJ%f!qvduUt^F$TzBsUYcF`C8zb!9yQ%=mvq{{ z_2hcHc%Bf;#+}D!saafzzc#d~YgYV<^s;-zdPsfG`npf;NtQ@;UA0 zg5_8?(Ve7%FnVL4^*+3hTys$T>~bJd%G30rp3X)e7Tt-G>%dNO{sQcstfP3dme*G>BRp1{5;WLEO! zNaIy30sxYNK_wNO0>J+OcoH*}CxeJz#Ua^vnt2$7jwNFx(#XUlX&3~vyspZzqUG6` zB7$2L;j1pCJkmm|A(dIv%XTpZWjh)<7=j}Tz^i<$6oNr+1%9G@4*in+EUn-VA8URw zz3~ET8fKf~y(2{$8)$Yqb?SK&3vE{B=I-)q!3ERCf-z%ktU#DP*vdDPoMJM}l83j& z)c5BZdm2>XDN3~C6(tnnpDp>K+@|3b7bmYRpJoc4FC9KgN%E&@&Q^?KudCf%+V)B6 z`BGl?pE-O}_&MWEL&Kg3@Wq#h^&72QQPs4s73*64lF56c=vKDEPqXMZ5!!jPL8x5C za@SKm#453vqeO9aui zxKgELRcOkbi~G$z|sj>_`G zQMA-8H9KZ>OKXT{ww`NvT(mWgC7`02=jWXZtlffC1D~OUn zWs*yF5`+N9F*B1aOjjtX?4*ExZrAi^yf5$<;XG=IZL9c;!5986*K95f%x$%A7D;b? zEO756>;_i|4#iZ+MHTl)fP5w49aq3!2h{B~8RysH@XfWRqo(Q+%k~&8;4(|+Tfdhd zDJ06M5hP;Lbz#kYEo#w(YRWA^JY9IXxXHpQl637fy{9B*>CVz^#XenmWRmBvOA4`d zBZaGpuY`*kjJQp4`bLuo4FW+@RV6Wbs}d<4a|`)&=}`?=*`l-ad~F`dwSkVI!@) z2F`yu!`u1uKnljkf-9oiygZ`%@{h zzfFj-$!!>oBrUvh2Z=v|>~xvGwKUh%Qqt)cP&#$w!PiWN;@(HNvbTr>meaKswYGAT z$sEc|h(-l^I4au3N->0*(MK`yWfg_BevJ{oe`|>Y$Lk1y0tgf8fDIp!K(6X~J zU=`4{JDc@$c5Zc5lHy3Dg>KAJ3#Z)7#yKQ(6Kn;FtET5);Q#?#_Lh8Ato%^a{55QB z+r!##hF4IUL=3aOtv%dv2;_XRjU%^s@fxGEv+~NSO?Dc#fOK7DZFLC1{?E9M<<{i{ ziMB1Wmt}$9dYHg>P{qJI3T^~f(c#`6Hm6NfRUsHBDsD4!a&MOM33TCs!AP#Z$)Mu=$J@4;2hg)uD=2q_DW91rXd@|zQ)r3A%MpT{3ymwXWOU~tk2pE%c&}F0ehpt(_y*Ul9mCkFnRVYz#_KFbpvQ*=GX>-Z!ouPYm_nTL>tnAKZ8nqQpNlsqPIm*+& zEH7r)G?KQO+Rdw^-p9_j7h3$Wyi;6}9I-5N#?lCFC=umE9=7; zkZoWEDB%)#=ft1@AZI zdt1wE_f2eh)n_L8TI=&&)AaIhV+Qq%k_iai8lFx#X6dx&I#w=ZcYjvxX4_LX1k*}$3)|Pmv3FK_kJ53QiP=a?rk)BUe8}nmec+i;jRqI zrIt13xl1j&&o$OK~&b;d|Pe*>w>IL<-fSD@ToSn78( z`S1kX2im83LbPRp*(}SjaK%m}MQ&7N0C?js?R<$@e8ie2{{T}gYzTPHa7h^|-J6UP z(4MERl}O6#OX;(|{WQ7DRt_%uzg2I+?cUnoqtu&DzhqW%<~_O<5=M+jP~<5xN0Lh9 z0!8EBi~tXm5(2L~(}5A%iF+ z90S0{Mmhp3dqmZV0$ZCYC5jmVmUtOQkYD{04z^&(&)PGnSWt#Bg)P%Yv$%#>KGv-&d6#Jmv$TIAu=3cG zwaYUu(5=A)s>-6A6e`87Rqt!H%J0?PHEXM1Rk__aDshh_r8-hhO+HkUc9XTQwVLT? zYbUBTbs5^u{{ZDxo6BWmCPCb<#^7>EKPkx{F+D4G4Mx)9)yg=ERo%C9?JQd*K_sck zCmVb7p1kB*y{@YSO(txSot5T&u438;%OFBX-r3p-1g?1;15Zs$cy*_;npmcWSzQ(+ z^A=XYJ7)Q#*r0+6;oq=4f(EgYNvT~*DJHwP?`yQ5Mzw7xwzo2pa(vO&GSyk?lUgS9 z*4|p#{P8?q4W5TcNUVv zB-V2LipEqzSP0~8zH}@J4S<;{PT`)IHPd*jOlH?FbhzYbEbp2dsDpgb=GghMzm>QK zV9Ke>AUnw?psV(JYzXEnkg{BTo#(fVFbvV4Snej4Foi<4=+Yoa18b1ZSnVSz!lHBc z;X7K-Zf%lVr{AT^afIo$4|Y)9xW0+r@2xD@i62!z#+4PSLB7VhywgR*qaSBWpK1bCPl@ z(~UaKB6~@tyNU=D`EDLS*Ae7SqGF4Jt{deFag2sJ$@-~I3Bfx%sWh6pZ6vgkR!-d> zy^o*vbCR1^jhbB(Nxk`c-RSi)Z7*+L*>u_N8s6UC)ls5!caf16ypLob(c zv8A2~i{!-y5TeN2o#ZIKSIv=MQqpeXXT7#DDk$3|dpzkj9EK{mOsU8R=ECjH)3{X8|8~{cHZw>>1(Ywu~l%Dc~qr7XYX07wvyh%{{RF|5w}PIBMM0aEO-Qt zmg7sei%@%%cZsIAWMX96u)3*G@g1ZfAOd#+0QpJdC%5qY78ip{orRJroq3{wLj+T_OJSx7C=4l|LCE1dB(LG;Xo zQX!Br-n)q00Aj1oej7WrmvarZ4W$?RC`+);^D=Syf;=j7G(k^3;d)qi}WPLkOxs8z9TuBU0(S4!<&9+BTA`(iF zYqHg$owSI}lu{+sMoI12fI%{lWiggfBd~COUIA7(#z3wcM$qHbFD&(0U}geYqWdh- z4<+Vk+?ARz`@!6Rq-s7wH#1>&w(xYMoVinRmphE2n{$i2B$H0kPiB&mdZ&GqqdILv znWZJjnr%KwCC?UPcWphKd0F&-fWAIU29VlMi6)m*n$06!3hb$pSB$RKwY!~j zDR{Q8lPshHj3eEMz#m0uTD`ux9-ny>h!W-)=6KwMkyVfu42PCGvK@dtg4xF>;@j)} zGU61qwa_P@RkK*k`yh=CgRx|Ytee$kNme%~03||@_~0IsL-F;;geA0|>I<9eISIFG zSlkD;5~%&;c_0$3*kxv10CsL}znSre0ARD4IGn>K!^a7mI<+g+q@Af_e{sn0)M;Lo z96d_alxsQ5mJYP5PHifV-=T278sc)Q*nAFcR#=?7*}{c6=<4AwSK3CsS>B~ewCU02 zrO3IZ?4wOW?iYVsTD*~4ERQ2frWIB)xqOCJ0%;Yp%zHNk{Ml@Er+ACQHl8Tap^8hS ziLM?vgMsC&a(Pm0hUEww?8uBfiL}PfVQdyqYtA$;5iR(&ZL&vaG!CujN~7g=MnJ5d zXk|tU5Hh1M&Q&YC)3sa3T2T;)Tib}*NWpFQDqYk_2}e?>xc%6}0&-3c2jKM8Y`(o( z7@ART6O?C8r!_fItqP6~PBGr39A{2&aGR83x!{n zRaaIO-*^MZUL}Iw<4N%Tk$XZ7?$4fM#dp<@sQ4>D{m@{vJ8gu$qc^L40@wemNJ~zvW(>#e;i{k zXLO${i;Hz6-J4KK)8%a*MO-4OP0n$r8GBAh%A{W-oPDZ`YU)}jMPA9bB;k17Kc%fd zXwL^Nt+L%fu-z@ZD{~CdO&rl&2-Hm!(a4J;OB|b$M0F0X3a|_aqPYt%jQ25F+C_2T zO)h!jwSqaPYs+xcN|7STD+bY7fsw;G49s$QVtFNfq;pzIF<)Pyq++#EzL85^chg@p z<(^eG+xnG#TY6M>)widYZz~@IX?NO=mvJ2P$8l?DUNe7hXXU^q2uYGeX=0XG+F(bS zwm_#DK!b|)8-Ec+bdPxiaYb)4>|0qj%F?4h?$ivMGQ~gCp>aiR+^TtZx!{X zs+V@2TD%d6;*ngOmNG1$POXeC3T};q1`6ASPv>d+YOGh9Tf_qZ%(3PdkdVs9Abif? z1CgAQ$7=m*SUQqYRO#ylx|WS-)3evg_tgBYVyVT&)SLH{e)N78(~C*juaimN?mJQ9 z2_{#zy|fmSTn{N%cJbt)4GScRv@18v7!Y<~U}b@-w~}7XXEIqb+1*A0+s;-wM&vvO zX_4D$Io!E9Ip?Ku6YB6wbgdP{u!2Nu1dSj;+%WS10ZG6Cc+UgUyR9y3$>M8h*UfE; z!Z4xtU}Tj>>w$xn7$p3p^{gi-Qj7Mq?W*T$PRiE4l1*&<{%G2qWl^tZQM;!ot4FHS zRj&Fg-@T2yc{R(cTO>N0Eyaw9G_GZG*CB>yw}v?#;er=tJ5^%@j0I)LBW~AIySb8e zZ7zFKq&PD;aLFDO-Cb1xL6AW?4Y-ftt`KS$R<~hgxS3g{1=XTeaS&iy9jERiCQuQK z1JH`H*CWRlI8 zX5MvU`{?9zktyK$fQ${Q4ir@BW@TxbI1F;mSjhytNn*-We)lJkxlsGC0U#V4S4^Qf z-9>UF(~P8(Piv;V=Ms<`zt&B$D_x2dRR&Jn576d zmUu*FPOZ~ z1$lPcl`Q`NIsh3+U7(_o;+jPEz8lk{b3Uc1TnGfRM?90cl2f(3rkY{{2FXT{F>pyB zoL23YuP&u&_M1s8qq#F;T|P^b8$k(DOQe?uGU}vlW+dT=1Mdpqog6*dl`4FZwW>J9 zMYnq;@kv_F?om)q%I&mvLZy2r8nWk;cc&L8C1kAMx}fi+lw{>(^j6o?tvpx87`cD@-x() zcsT&%k2$b6cag>|=Z_~UP+TDefhcyka*Tz;0NKG{!|wx&QovwUmiFG=!)^;J`6MYh z84?CP{YcN`D?8yEbkvtSX*fn}nWUAy$t$tYQ~dsXsd zxZkv|krOBZ02~0SH!eE>GmLNsD+-uuQfXc-THLaWR(9{Mt4*x*?V+@5O(fmb_LOFu zy7G3@w*LS&+dh@oyj`e6Wp4|3hT;XA%!1L(h&<^dR$wA_QzMx6XL~yWS1t(1rSQ+h z?SI3zVlplKM>JuL?d;pybcm2+#0cpalrNYGR9=ck4(;9z4zLfDw{Z!8CDRg?Wo9`d zCT83LZb<-VlHJX2+G<)`L2(37HM?Au7cjeFrc}<;Bjl`#H!uO%k)8k0cft^UU!1TBYJgZ35cc+Q)e>*zF?AJ`&Ym$x>a|msKAz zB%bxuS?ZewnTk|0SwzssD3i}177{LFVqpq@o}n5+d^QmG1VpFHlAr392> zlZ~B{PEBasuV-ePXzZbhrl$!{+Bn9}NlCtE%$u`sWc7AiUN%XeUhDoUv9xRJ_}%V) z%O=vEWTx5yBIQowAyr?xRk4Bz7#&Wxh5TAIjTTGG%^_f$dt2LF!69_IL5;5-!UxNp ztQa$8Nelr1e4+mU36rru`xgi$gbQ{?gx3jlYaTAqpXiYk8JICExxir2e)0Zlb!z8bLQ_%W3JWS9s zTi&Fq=mN5)WD2|wnT}XG_vCU3tIMvzCJ2=zQosX}3Xz^TAm^q}sUJ%6W8w=bqMHU? zN(l1C{s?C;VjF;NV%V~*WbwU_q+o_6ahlCtLq}<%iu=SmcAar7sV0vP+a#V_ouHYX zTYG;tdvr|3ttHHHKuf9z$pGOL!7Gf%zLbp&WE zEMS^@i@6AmQaHmjjkEv&3NjBP9QVa}3>xF=Rz>t}Rw%sUtsTv}MRL)Tf>uc1D;wjg zNCOOm)Ea%mU+NHjmj3CkQPeEb9EEtc1Z8+J_DI@uVfI@C@AyPpjCk&^!BQ?U_*y>h#?3&HJrl{gKmQ-1_R=$owAVp+&E>>6) z3@Wli9BGE!Njc+@kHE8OD%ZXWz0)*(MJ5ckmzLXfiQ;z6!p#g3Nr_oYh~-$zZy;_1 zHS2b-X?^D(s8oJnc zp`_8GyT7)dO~2Ev($+YxO2m;tdmMsWOQ@wNfr~;L2MWPJQPOJGt>6z6&EgGe^jhgY zB9Bb8zm5$;+8sYfzJDcRGHISp*siW73l#D|V78IuV7BP26nyEed;;-gI<4Kuhdv=* zYMvWgneXhpFRM>7U+pq9@aVAJxi(STfL18(9_0!l{o^J89E_4h;|*s})O=~;3r#Ch zwu0kJzdFx|8LTbd!Zr&B+U>3;)9$56;bnqICYDDSjdJc3%)3 zDz#?kI&zDphkVjaC`wbDqfv9kLJyV72D7O`6yr{EjOzPNdOXfl>BUAePBkjHsI~7d zSjJ1;ZckL2{T}eXtKo~N4gH+97t0ju3J7CKWQukf2g_1$#1P?uzyR@%D)){w+w1K% z?^y7XTF>HpNCL;D-y};GrhpL9LoU^5?id28wZ39hDuOxqi{atHd=~Ri zIx7o?kIYE|qB>9W9qx=BHwFaxIffRzF%tGw{;|m~XF5`aNY+&3DllqRB_ozhoa*K1d1&tC9ex^)dE+WW>gM$cW1 z8%@@H8+C6C!&S7@TkI0s+E~dKn>;ovKb>%8X{CzZ2_LTlD^FN7L27dF!PO3zHu zP&sm}O2>I|D_ey?qsxhsB^;tJL-QS+`p%&aoVrf44fegI*)*4Wozyc+ zdnK`qi(Gl}6_(=KLlWG@8#Tm%Tm@iGeKN=5mx(kBYg^NLyP}QS@_lg3CeGG))!U>JZN?cJ9VDjyro4by4o^(+4u!8191}^PYn~p|WwyDozIKMr=Jwh~Ni5Q9hIP5Ox^-o@ zx)?IVL&Q|DVet*`kNj)#BGOF|__pfi%TX7Nf2>}#R+q6`O77Nrb)JnA2qx2)ckd&- zjU!;~wONY_^v?l!e_yeZX!ZSKKN@LwT60@n!FA=UODqYSS6dK%%AQ<^i)!}ayrZ$c zMFfur7s8nAHWIw?mFTQR0Kh;$zc(pHg*Q@lCrUPYNyZRTtM5h-t2j+H88>NKJ@hk* z6Ri)c)0eZ7NzL-c3Qu&^Aj}k}?wD6T!3%#?#WL?NIC-VajmA7Dl z;GYltMPV#c>6W+7EbN@YEsRr3CFO;}6=>r~S0>&Q8IVXYh}ev-a%<9);unQgU&_}my9H;Cwv&~ywe~to0g3wW+e+84ijoVu{YiniE`fhqNcvD81r&-wewfs>;JB zas>H?(sC7OUfshHuLMx@_ zGKyaQjceZh74Lg@zW)Gla>3}-bZISjzimIS#O6+yVH{|-?CBz^Ho}ZDN{oT9o&Sg1vgIaEYZ)?f&HoQxmg z`9K)p9lT_UqAczmqA3ay2xU^_gaah0%j4z%?NWIGKnLZnYMA-GRJ_yaf4zQtZd!4Q zO4eJYWURIAqV?S4-oguFB!MLJnkJXbmIZc5n0(|m&=?dYUuYaL=y|MkxVD<%qB|8~ z-xDkmsu@+Wn7IW3JBxx8Isn*iPJIq*OPLH&NoylSvB)=!0~i2-9|t5bImqFLMoxLi zlSycIn{P4&bV=9A{Dchw~AZ!Nbu-7am@*S7xvJ#2ZM#gy#y|y0IL~Fl?SlZs9=5JpgR+kOv;f`UE~&8#5YYf4p(y6Sy61PjPw)12>I&D5(7e=+$ zuSCAH)Z+fT~f zaG>-AabC!LFFJx=DO?Z&r~rjij=Ho7Uexr-j{kM%l?A$s@C5BY&#|;GdI# za0noDT-GeU438wp%A?r zX7I6kC|Nt%$!Y7Q-_NJ1^O^8cNLg7`K*k$6BzkuWyq~*+lg~j_+rbubnE+VX@ty9> zR1yFf%VdvGtO)Ij`enQ&ZmJsQ1X0G=Q$Az$JVpU!9CBC;=klcf6}EW`3qK_=a!AV% zJ$nK%>&G>`bD3M+sXaHcj{dh#^dstNC+@}d-LKBq^gdy^@Qt$;8JNYK6B`xVjD65B z#Akw7u_LcM)^PBJs=C1 zSJjhvOHYdttZ@b;ZgUteNWj9W0D+u3^Q;z z$RnuEE1R3bP#g(iiCnJY&yDP$oE9H=0yqNz@ty$$_fpPPuPUGR?>4Ko-Sxkf(tS=@ z;C1+Ybh7pQZT(#ND(gkMorzc#7da}ZdG;8=1Jj>;U{+&zLVJzG+mz#%$s7-EIvn%K zIj^qnJTYnu2%uC1;de&FfzM2XgYG>rI@W3MT(kY#ZHdq}c5YFe?dW=*NE~E(*K9My zlC7~})N3PuRv@tV*xh-{{X_c^5F8Iw%&vU+K5j18y_%U8;tVU>zw3+SN^lx zM^{_Fi2%6{{Up&-BU>?y7cV2ey8W#{4X(#v(309P|Q-lr?drQo%;AWd@|1y)(4g&ruEXPV3A z0Nj|KG^aunwMj~U3_Y5J+mpY$7&~54dM<4~C-B9ydN~a0%}0_gUsZP-TUU10ipu&l z_SHSPFM>a^UYX*ZWZmF&qql##sQutpZ$EadW%dubX{ zBj1t=^*w7{xVh5pyjO6NI$b<%evr?r$8wD= z^}efOms&mfg-_dG&5w7=ye>b97Aq50x@v_QQp2j%D^sOORgW`;K3;7clcxnZ&UJZt ztq8#*)b^CH9?FaQcsm?uJ5nukHuYE#J(|(4HHMVn^Myz zk}H@Fn?2r<;)|uTcRG!>oh7}(#eHoWNo^!st)z_k7jVrSuPwV<{89U1d|~lN{2(^p z4!mjL=@Y~Hj8^^=k5usG^~QWxVd6;R(d=~Z5!%XbFEop|ELz^$;tOlICOVp2#u!8r z827v}`$1{bp9$-4ai?A0S?UdQqv|?)-RaZ+0BAw--P>GQ-p6PylK$T5q_<>1_hJt+ zAtWolx&Hv#hsKv4JNUW#EBH^s_K;hDZ2U)?;$*3-YB1^XeVf6M+4zG>nrZH*ipI`s zuMoj`V+e*|ZoHv(`JQ)U$CY5};4@4du{cU?;J&eqjY&RODPXBq#L80Vv}eqyQCh(z zDOo6}ru`mI?Fuz;^l=m@`)XCWr;5Z#bPQ@!_!W! zSli|w+WSp{S!^_&Gf9(5Z7aZ{$C8~wxZSt7P39eR(A4At2o4FQRi=DWG8YdB>bd)eSXmz--;K;7W&_c zCbibJElTS9PPq~4f7lCRc1(9<$7`SbQ!GOZSSa zb!9lT;^jDURa0$ps42}(Jjpqv`CmiN`jr~hD>$bPM&WJtl9VNXwW4rxR3%jmeMq3D$tOQN5~>)Me^fQw;gxJtqbF?!qGfX&wt~e zhnHyzz z8=nvAF*fUYV}|DIP1C2=ZZ!MLh@&yPta@~^*xtm_BwkOJWsYehNA_^poh0DlDATEQ zoFgXa*V)EVcTuM|DM~HJm0y>cC1aYVUsI9Eu4-*LDx9mHov-f7Hgc3-E%oMhi{)}! zET4u_YH#A77iu;W$1bBDv;CQGCDQF#Wz(UE%>>eXu(Yk_!r~JdM+z7Y8+X(b=(c_< zy6~L-AhwRe<6PCQ^t=1Gq!CRRva*Ka;`KbBmc%UbOBu`sWQsA7&QHkF-26fDPlUW5 z@d^ziQ}DNkHK`@=h4tr#?AKSa)Sp4QlFr*yk4BYR_TpKtrMmlWrnW3I}Q-t<^ z40w0qhMOLrX{^9?Z|wX305?y%xRxZkI%J^|>PW5kgo0^pfmxxLM|d1Ed3Xz-rm2{^ zZZxP))ni>XIJl{M(T$+wWx3KkS>Sy}*8VNV;`%vmqPewJ1In5!g60_@Y?6hebUX}T*QjW|Cb_amPOcjF zLwF^E_e8v%W|HGi5j1jzig)s+nh-;X7@4PyAIe8!0qV7_8r#G=ZL)Z0T0?Fl2Eb}> zF|~%>hU2F!lPPN$)v%#dBxqM`g$I|PYB`N)dpOshENV2?BA>OSqfslhE=J=Px~92X zZNZZk2<$>-5dVI3W ziEc#j$1Re~s03xFxRBXO5f^2`NI(N>2kQPgk6Z8trQz%8ZY0ps)vPU*qk9M~k~JpX zn&!mX%HrG08&*jf6oB$8l^E9XRko?&y=LOqP+0A*;*{zdZQbhqt4KF-H=7t2QHh|r zwnqccjalA1O{ZsS@*QUOE2A^%_SaC^MQw9?sOanmnH{=M9NQrB$>P-&qxlc-?b=Pd z)R1~3jjbxwVTi4J)V(Q5#$2;fT$86I?%i50O(vxoM#?QTDPZXP8nr0XX~qlMDDy68 zI5|!;PS00$6w>9CUad+k`4zsMr{DNqJ6jpAgcnZe-YBuUxSv>xD|uv9x3!Mp=hK8+ zi-);u2bijX=HMLjH`+UB_OMJO)HUlzOTyPzD{BkeO&iPhVKngDMI8QQiWQVbu3Lh| zxvz28ynUc}b4*jNTFoWB%qcFD2AHZQ^Bz1z;@;rH6I;d6;gjw-cPW?2@jJ_{GhdQM zxngwPLfR>$hE`iQ7wgHE*eOQ0EjZmU{o0(JyR(Y-@ZQ~XR-~~ogz7(N)TJdkUs*<0 zl#|x#H}-38TQ+#rojdy}{awjLIL1+eaf?@qlzr6iYf4sCEvk1{IA)o3U1fAjO)B(V zeU+{m-Wdc@c`3SPGvqIm!Bn52VzJ|MsTmhmQNtrf(wHUPwU=^a_4$V6U;qKJ$2cc~ z4SE&D@cT59EVJ4~bFwueSl%}VJ(DCQ*aFU=?*WTrf@_(B!}iw}Z*ya-$$FFAd4fCH zr?^{L0NX4P%P#5SivS-bwnmvy7Y$zi9}`-XVw~Mbq@&F=`P=^UO4EHWWosv9&mO)W zl-%VQDsuR_VEx3tZ8~XLw3~d&R!rh1issfr_QKZr6_MH}EQF)5$C)C?p-ZkdoMQxI z3xQm|t@hY1rJ7r4#4>LCECsh*Mu0HdWn4!xf<_odr;nJCn(Z%bY@?jo+-bJ=cDA#5 zqDD}xB@O03mn0y#*u;qPM%4fU2q0)fr}$e`iEOUsywUEh?4C;-yK*L3Wm3EB=ZV|* z!J+dS13K(8ENPI;p!ClbI7L*IK4_+&H9mJJ!cHsSis+v5R$E#*hMqN3>u6c>A8VL=m!eWpY-60DaJGah55=WR>&K^bF$Vq1^xg)L0 z4l1M@i+bKNYWqssG}CRXX{OgX6lE6UQqqp9(n{95TQ#a$>vhw!I9rQ}?k;Vlia6FC zh8va{jz+l!Q**1cEJ#M;RIcWeYVX0I%RQubF_viKkQn7KvwYDK2oppO$4r1h3JPO_ zH&&hPy~LL*slhC55yiZgh!*lTmpd2jf-f~zFEpf%>$wo1+*D?x^Iu4ujZ(nsw&}Sp z;l}dDs5TDYFw_)_l%Y7`JMLFF1rMt zD_sL$)%3BYYg(iizEeCF_R_p|rJh3_*i`-Li~>=eWfA39E1ql6blLAUbdKsvDJ<3? zv0JpU`B!pnP!dA8S$vW(ce62fC4uB)j=f8>8c(I(z0%rBc352HbsJdRDR_aD2bw1c z3YBIDV&|Qrw=_=?sl2wDaLR!BcK~Hs7!t0stL2-Tv_IKL-OO1MIa(gtS3$!#k>w$Z%Wq}nhL8Xim2>m5s^yXmjs46) zqK4vFmR?zeaLS_IR!QZGH~GBY6(^YR^mU*6Rz9O`JHjguhk{bkCCa9vo3^gop5|LR zal&UavZns4hK}o&PukXP$5#FBS0=xeUt@^Vn_Tf1jN;NSbvYu@G|LCQwX=;QRn_Nd zSV+cqQ!1okB2-0?92ezUg3mxplbHR8* zdv?8DPg|ePirP4!va@xUFuYP+Zjw_Xh@p^fCNddGN8Qk=E%6tL1YRJyTO%7;7!h`F zd)?l0hG7_s&XdihFE+rrttPtfMH~n%ev} zl1aPC-MimQS-UMeze2RsS}P^erogsp0VY7fccL>8#3LgX3aY~=K9yyo zX);)?%j$QDDYn3dc$>}Kq{s8bSZ$QUFaOpt4qbYoU(tvSvq>3V8c z((N{y-V z7ceU;d2<3aWJNT4`DQ0|QL$<40fxceIEdXM2H}j17$cv(hhV$5mE3W=Jm=Fj z$6K3OT09WRBgVvl2bQFOckKY+1M?gLa!Bb}`LMZI-^qn!0YsZoLmjyVcc43md=5Aq zdUw;5Twxhga*~dfB(C+cT-Uo=-_u>XaMX;srzq7>hd03%(oI_Yx>{SMWRta?y?BeO zU+pnE>=DY*qqH)n_`{9B9H>`~nDPR$r~ok;B%d_9vbnOkXr*Z*k!1-nEx5w&01f7m zxW-h0mM3WR#djVh@e25M<_%5ZBFpVRWw>yz!X%fZu8{^JB`JrPt{^VCE9MO3-D>Np z>Jz1%lT9VXwXLfComt_!mr;ot0+&R2a&3xu%gBz=#K4ASWned0n9`Gk;`U8BY~Nd5 zEwt9wcHHN9X;g$~87sG~o$b|gYokk6w@&EIw0%QP*?c843psOl8!#uyA1rLD057&i zjGTP?bA|w%>d)dkeP9Q@nket#Rxq!YiEW2C5*?vi%>h&sxM1TWu6I+zliQM$!WcY3 zSPV#{pa(7n?D9JDsx!_y@jADK?j@bx#w3zOOdDS?N9K}w^2sBh1NTIN4=TOuUP?7@ zCj_L@w6=Ea_S5>gnw@HPij!*gd$nu3$!%o%?Df;JtaU`X(|*VHgA~@qB1xi@8F`n6 z48ejvK4QT@1GgEgnq)EQmg36Qi`-q`wdtDU_tV6VuI%>i-3+7zJJrggwg4lJ8pg?P zZSJjZQZ&EwW%CTt;iD0fh8=}TVu-$0c?=hJd9I61)Zw_efnEn$qDP85nH1t6sy8CD z3@j2djjX?Tg#$UPB}=M`R=xMvUDHcl4v5xi+Epde+9$Qr-Dzg6ySme<=+;4^xSr-u z`FMgTT}rBe@U*V80-H&4CuLw*j4F@^Im6dux3#;lxsus$tv=NQ&t%ME`$EScc8t7R z3}R#(1E~!eInH<*aB5LCvcYpSVrbiVkT5a4ZP9X0N#O8C2N?IMt=(FtnKaT$q(|kH zWX!BtT}Va7aJ&u7aT+Ns%&G~bsl`T0QFfAPu4l7Szgw%`+F9PsJEdmo&QgPmT=9~U zc8>Q=H)}g9Egj>&mc9Bv1!}3T_@es4^7H#9!%?`D>Chxmm~{3LO4hNesv%`*mNb!r zDe}v*l^|EL#{MJGFHMczs!6Aov$h(<8=lS^tFv|XA#pKgNR9Bdy7HoKSlc#S^Is=E zsB|0KYv#xLOiT7>jBb@1D!>8;Lb~o&Z2iVz(!I07zBfA7nI*O5&F!U~=n&tQW|GS4 z-o%-0Qs>M*Q_ZK#b3B${<)Rm}V{Y@i@m@XQ*sM~=(7->cN{t$I@i3G*2FdxEj@WH5!s? zO*^hs)Mn!Dn|#tutF-xTyHV+wY1^Cq0msaE3mF5Rfb8TBfYDp8;cZYm2;{VQ!!Sn| zaDeCu+Q2lbz%t-~KsY>rc%rhtW&D-D@EU*ofp@}x&&T)F{{S<=G@I`V*y-}>H_Y~$ ziE`3uv0Fg)Q*UBcXyq3%v^Y`=t3{E(3dCljlf>T+bp@C0vq^0u0%H)`dDg~5^DoZN z8-*MK!ZXHpf_nH%v%cjfS5_l)GqDVK9S(TM@bu@`H7K%l*r*8^1AqYorU1q}^!D|y z>!pQ)Zc43HDL1N>lvbYPRhs3~c_}r%=knXdN=ZlAQ<9GNjoY>T=d5hoy3wyQw$#@^ ziYU#5_V+VP(ixH)R*PUf#$z%&WNjp|EQfFaCtPr=E$lbS*4MX4GQ-T^IxBEcfZIwC zFfejJ=nZSfY#4cMxE3k_Lz9lDuHX+&c*i{FHK>|Jw1PE%FaeSr$`qUuNMNBr8P6l1 zLrQphGK-B)X{jf7B%77@yGq@=4mg_7lwCepHDr>#mt8L1mET+Sw^K7tx44GzPSeXd zX#}2BnA%wX01FV#b{5M&UBD19YpQE|+?i*;NbV$%$Ql)N#6SQcNJFt$<1LcGo91Dj zpdBqf$4-gVXr6qm|AHXj8@Skclwm~H<10J+6!$tuCX3WesjE%TA+YPj;uqHHn0HT6Lq1!vWngA zBxblE?%JMS(5C>nEc;owZJ?FTGT7_&72dg~$8}^hyF_~pGfam{wOM0|8Dxb6JdY@X zICnI%$s;gq<0BX(n&WOfI5q3J?hUfV1FIE_q-swARO5bofFG0VTy*NfGUsuf7+afJ z^J{jLTpjsu9#)!qJs(^3&J&VJxYe6&X&A?(WaZ4P<-45=1i}n1a$|#5-f<3y)0X^UiUMbbClQdTK5*v*uc~w%6WYKHW}t z2`wh%q_$eCzeT0G3p2?wv*Y*R1P&x9#X;%Hx~~J!oD6%0&1Ukzkw)pvi1VbSoY)zE50afG|n=*0e7H8}0;=Fv#KCB|#rH zz(>owp~pQwYxDJpB4>zX&+c|~aS>!!Qh+7YcJ6X2#iSw8Q`6JO)FElm1DZNmgvnOSrYBo#cP3u@=;0< z`2#SOe6paMY%`+>|M(+R>aFjYPH4-6!4On*N7eD#=DFQk#|AlqR{U zr=q>ndhNU#Ywk4-wzp)99g9zG<>Xw-kTt|*Ln%gxvmtzd`@}?QMVSzQwd(P<4Vc%;Lw15F&R`ktRSMp?cxJHSWYI!Kxa5o1NB!*3` z_jZ`}42Iy~RMuCzwCvHxs9ds!8H#dV6;(M3QTQXc3|JiF7y__@e6#j*r_P*|U4CaK z?Dmp&X}t!-r0jjCNrGN}nDa;DV|TWNN*(JS@3jr}z>G#w{c)GQ^wx$-U-dS+X6 z`#g5?%fxZWT1f(iW(v3`1cA?5#k$qC%L|rUZ7vN-BMx8f7a|sjsZ~;4W06W^@J35# zkhslvvTB#tx;(l#OG`+mXl0(_#y_)3EY|L_BfL>E!OI|L+YlRaFb7;Ke+z0V-@FeX zV0RgJFkt-dDvZ2zAQDs&oN-fzRii4OS(PcR9Ac$wMeQr4drMt6R_l8Xzq4_tDhjPO z?{?FAt^M1pHFc_ONnIrLZk3mcH8|p$O+!Vqv@TF8LwfG=mr$tae$I-F7#sl4yJ#)6 zoL5h!>UL1PP)Ttl7c;4FGV%~q;O}4pjO41|5=Jr?kxMVbYl$u6x_K^Cl+C;{F<4em z%;At9nB|zZS(pVlPyiV84~8BI(;)M0yjiYkGV5}gCXP=h$+3#lcI3CW^QDoDv98p4 z8b^5?WR(nSj}?ihhm`8x5v2KI;TGyP)%LP{sw?7ezb?94u7wF#glYTkqULT*MmASX zEoHAWc3M3(dtLL%d#vg2b1nRK*EX#z3t&oL-X~tcRy^N8MSMx=_8SG{iAPh15SVic7$8Q0w@d{$^i)} zvv%TYDPr(=noy|b;->jh36JR^j79-_f}SIs-7DYN=_;&T&YREXuU0_i6;I@ ztM$3=5O|*DQO1|47F&Rk%?eD>n~2F=p;k@991;$40sJ(e)tVnNR)pqc^4+$Fa0yei zI}ld{0(OC(I@gp7S1P775y%mlUNg16;bX|F&{Xv)?}U9I-AZ$`9FzbvOx4LY!vx3sLlT z)tIp&#caY=omP2exR3!Z z)yjzBOt_4fEcjMnoPprbYPVMD9G9yLMA3%KWxUnKNhfPypKZDCn$fh@4cK7=KIPzV zz{_B4?Y+~FWozE%@Ws1Y&KKRrQcribsd{PhJz@`tzBbbswyUMtYcQr)?Do@} zO;{3kh7pvO%!F(?#n>ej;Y)CO6Y-x)x4E>peK%PzIQ{&o9lJwk@{P$Oy~?|7CmC3e zLI6ESi$#AdrJ75C6a8T=l73%82suB2@AR*8b8U5$ibi%(ljX*Zl7GC#OEDarZqGP9 zYnFLl4yD}aMLTQkoav^TwcJyZ(_3u&-B}vP9f*Q_m8B^5s-ZV^tJSEG^ z$gQm&GaHK=YrDB3SY8Pct{&#!{UUwa+U4MKGC+iq2>GTP=hG&YuP;@tHnwBAK@@Q} z-d0_KSy+Mr3|&q#6cbyPm)>l0t;LzKciQOI_YW|cTjp0>mNAwGcgjE=Ko|zHSzKt@ z(W_BLFP=QfNha01LEhS5-d$}KskhgiS83CWa*r#wG+mRw_tH(hte>6EkH+3He+Foc z;m-r~jr5h3*;xMh_KMwpk@ds7blK%k2 zcT(vvG;&EL)S8pFqjhqmg}A)9Rb*)-d^;+kRRkdUR9B^osFEjExw$*~w33FEbAh*U zLI_>FD+7(jvGpBBNUfMdsY?VXr!x6)IT!QM0>B?wt`zLI(?+Ab>h)2sF?Pl#8347yD| ze;8a#s5~wOn*nuoJ-7Vz4;h3;hXH|XHgG_}Ca_}hlgZ*+`?R>%F67kbf=laZFBvT4 zX(N>(NEpE)tZY*=KmfrAOq}5S!6vQYy)HxIEB$VFmv=Y!3LZ;<#3_XXf=FP+Rw&A% z@B*#|Hgw+<>)N&8n@Tqtevq+=5^IQ%U0f5LvMf%UU{a?lSzVigtS~C4mSM2)omC2O za;IvQeViz!;<=P;qOPN*lXr^MxUC6>GQD|5n{uBl*DO@!Hx%?&yKeU8-s$X>^*;RY zZ;#hRwzjqL29(w}4LqVrEF^i7(i1cNn7zS)9iCW9Nj!c@Se=Y$?i4xtQp@6hhwWgN z`R-@8v$Ta;_Gn>w651I+D>D$$vqr?I1`#8IK`NjUKP>d08~C40xVE#fGU~Te6nTaI zZq{;Lw#T+W+jp)8Q*PBeKmZK;SB8EjYc97|x|WrvLk#P-L`Gu-C=S<)?DI)4m;lIJ zlBnTM-YezvES{DoF|96C=DCt}SHBkR?$erbPnX_b7L9wUp57N5Dspt~DMlJLsmc2` zmd;Acl|A+7^+_M48V8NE*Dz|fbG^dG67goWD+JR;Azvg&z&nuPT(Zp<%mE@ysZ;F9 zK{ScU8|T&i28 z&AhT35ga?DiWwtjcvKT4nE63Yc901b>$(Sy?QP|j-&=Ho6LK!%EJ_*~D1)0?SIH96_sDN=8prkk>g(pI!uyIVDQ?EZ@jnft0TlvG;MGq*18 z`svHF>aTQui})sMEe_6GD+iUJxww}7jFYt1%G0rSYhBx(FvYhtOvD5CTYxLkC7LUl zY;`4y3#l!{v6Ce7MJmNOPcXvB8aH3vCS#Q|kO*5X#ZqTN#Y-UB*x(Z@%J4S{YTO zX2fbkF9)1g$mTpZj#8Cn7g@?Kq}|`NmD0WAYqpZJ>#SC|liw#2RXvRCFL^T+9v)MpywRfRy_I$)w_ft(x@o`4V!xF;hxubiL6 z5pVwhMx3cajKg*d5*vjhjGPRD2;+qW^L{@WA;^+a&m4;wP(UQORt)1A;I=rxzz2+q z=AK(o>lJkG?%GMNi@JC6e|d4l#{ToWvsZS1CG!6OfPD&Ij9EIBRb z@t#zb!N?ye0Ao4oNd0)Jzu_o^F5@|D{oIkX9CW|{bj~w__|^{vQtL;3wdPH=)2H0} z8Y-~1n=SQS4_%GzCL`quh3MOUUUA3-gX`Bg^r^x@$c(2M8NkMR^~ZD1UjEhN_P!)Z z0cMyg1CTckecPseI`BcxCsm2FGT2c6pH_z`l01TGTJo}Id?SY@59Lu3nH&$-zrP8A- zrDv`7(Jxo0t)HdN%xSjol4IVgFf+pE&?sJhq>Sgcca1s_q+w8cB7hqMjGXQ#j12cb zO6B44IswdpjA2GV0E`kkdXh872tP_y@fxus%^dW>UtYrE$OG`zg`#&%0 z{<5_z(7ti6!i<= zkWS*=s+asEa3BiLxU+C`fV_7DrhWRHelH#&g}?&=K)}yJN7Mo`agO*o%}we>X&L#u z-{-PJcbD3Rz1F|imHz<9l5GyjR1KTE6(A~LWP*6f>Cd-ML6vo-4Xm)L;hQ)`=QzP1 zF&uC|5$#&>YVk?Sy5sw#_Uw7<_>6vaU}{#KokD^}a5*>_3I`ebcHr^TDPk%w=F#la zx25fG#MMG6YLmXVO=)hHdi}?q-FSBP=Lr#tA<1Id-cO-BNC4xpBadFVzwm=x#l*4+ zr#UQDfC{AN3!D-{=Na$s#d^!?+HwFHlu5WQ)4@FP)c!*QuU_>FUs|A9)+LaJQ6b&| z2zYkO?jO5SScL$vTx52r;%mEF_HSD!_-U%?(?I2eP1|1A-Fa+i%8qc(dWmZsf z41u0tIL2@k0C@!RJq~kJSK-XF7d}LY(w{Jr;K&HT0Fp7B54tb_IQ7r9CaDC&D2NaR zV8K8IA8;5XbskyHFmS^?v9A@~k}A9H`LUcFu+B5=dCB>|mldpWn2u#>a=z_LZrZk& z_2^|d#U!~LuCM*8W?59X|efxm!vWeG=DCHG6D%a(q09Ivk{^tOg8zRAC2nKx8bzdTt;w$4a>V z2enKczcw+mXbGMMNf{@DlfeBe(uSjGzc$dM9t$ueoaAi-s3(D*pHWb){gje8G9hFj zI*;LI1b}gqjAZAz2b|IE>b+fAH)ij4muJ+DdX{&f)K_HhwXC&vR{sEita)+xer9H3 z;bQ*)o=PyRM`A+c{{UW@rT+kg8YEF1P($}Y-o)ZOj!LLrSdw`pb{OZMR%`1#1CR+g z03HGN@6SC?nM-HylD`gQlA;%exXMv~WiUH$fV>(=5@ZM)HSw$_uk z`TqbT}5aJqCLHdz{mjYZU~ug2$#h_Vvzj*NUZzum1o)dv$txS?d1)0$o_2vG(H(yFjZZV@ye`yJM}mxpz3N!z8YDkK`|B_?(&HtPXq&y2|QqZe-CO~ zn<2Y94*(pD5;p$;7e9w@Q_mEwJ(Dt=Dx&?-j$dy)cFzO`Mqda`GEby zywm>xc6QfZTkYif^s?IbzK4%nd^59w%PL2fB!v-f*r#vIeqqd<{BZ(}7*{>Nb)5!*4t&1w#@CJwf1h;PpP$QeP0k9BjlQfDb#e zz+)T?fJi*_=tmvs_OqO?DzlcB(YJNmSKi+@eXdWn#Y$v7DRlV6!1v?s$K9Q;)A_L$lYoVWINmvLBG z+)k0&>3VId%I&CX6Dg6IR49f!Q515>U1r>Nx|sg}K;-eQys}(Ib(Fb^<_|XBDOL+> zm>^%4;ht1f-4V__vOLvZLyQw%XQ}w7PjtGP!KS)K1v6wvmxW>g5(H!zV#U~lo~NAE zQl(yaigQuqQ07*ea&mPNidWGqUAHT)u~t_)@b#xcGnGj~tmKl7xs)LFZLJf&(dE;t zla=g#ed}^)KL?Y?-WAma{{V>YpuV)XxYRBsl5JB`wbe8oG)D_X5}4r9Et*rN+3aaV zR<_Zk%v~Nv@mo)d-wk|6tif;MZw^{Ts(BW=J(Iy<5f;#e5v8j~Dw{(KFhug>jyXu= zu;ooJ+B4#Aw`=i(PrkLWw$ZF^bjH%}b!&usi+x&K9ai?%OBzg-C=Jo zML7c)`M<~i023Ea)y1`h+FWg8be9uc!J}Eh1hO=5C)%tU;u-EFm(B|$Gd%Lfakxf7 z!Tq;~vSo_EMwLo)SgMeW)k<|-Z69W%q+uCBManU}bh><;vFq`Ri^NwJn!V-Lk>Vo_-KT{$4L0J>?2jCC2_(>U zn^(C{GTGW0BDc7-w9u$8IT0X3@MR9Lyer_ca z!y8T(JE&p11^l_Z(gKxIrCG0dkK>1oylE%)fBYpnj-6@Yjn`JQZMRE?x?){gX%ZFl zl0{ZNO9Fr*{J7%1OZHayYvAvUKMs6<;(v)B+B%-G@dL;A{{UduEiNr=b;~P#0^Zj` zj_%3U*juDcHklzIEyQvFeB_afGkX~B9e4~Cd|o1}tB9#X>T#z8?H_32%#!sOam#@6?uSRs=J-r(fY-MCKlr2ZkKvY|W8uFLXc~3gx_Vm4bY;|zqo(TCO(crCRCksWS;K9w z=`O+SWK_+?oX-nHe1O&YmT8jXv2cuN)qIq>=SrO=81g!i<-aqJw6m0A)gtN-}jM<1cmTqiH)`^0eEsvr@Ist$an`okC0967R%*D{r&GtlwT} z+Wno#`(}$A7cV`}hx}Kh%?wa#{vL6<8SY}awVkXSMz-Qq^B?mk{t7MQ--JK2-@z?= z;*W!Lt9=9GroS)zE1w0~tCTTnx~}UV6Zo4<+M6z-hr(a*kjZ0zBv8k53$z9+d1sDT z{@l3uz2JWo>NhvqzM(#gdtrMJ*ZdnMpiV3m4vv==dWMnVZC_2k7I16!X7YV5;@xgq z$}3Cw>}_she=gA`ST1FW@yN2AOf!528yQCsqj^-W<3go6U%O7Ns_8mT6sxRzL@k$kY=Fh8nav#0GV z;C)BHJ`nKb_lT{0RpUPjXu4j7;%!Q2k{j4OTj48cbe(rX)@^1R+E$xSb7iW-B#Eg( zEDqN2J2|hzzlGnl&XM5%00Kpzc$Kvo^*;`a_VCx)XOKs!M}Hhi65KE(2eY0A+8AwU zq$;Yr2{r!!W$%n%5BwS8j~eQq5$$eYQ1P#dbUi}O<%QIK96n|IQ)=+*SNe4JcltHb z$kV)9!PFMqz+sL{X&M9j(@;>Cvs9X!vy+Wj zyQxc<@}XZZgs?G;;rse37_{Xp(~^(4=H%RYom8N?m8DKew-~6O)$fI_z8v`DO@jX3 zOLVu@V}|QYCV2kMC)!AkYYgr4W4*Gtk|-J{jeN|rslqmFYd!$9vWrrW!hRtB%hvoo z9lo&oJm@E~ySKdak})hXJ5LN(X4c>&g&9Pahj0PKeo8~*8?OrKSK~v}VYu+k`)R%* zv$TCuYm40m`dQ+7IpB|<4T1&I9nMh zC|0Wl7bsGTr#@)GHwn~fMicjL-PC-n+Y^>$Sg2B~dbK8%PFy-tof>kJQI%$=6&ch? zxYLZJ+*dlhTwK19_{Z@cEj@1Tr-I4#d!&xSYdD-Ot-u7JyOs%eycf`^^9->A9FZ(w z$JajVq-Wy?8R zW+7QnF?l9z?j!hOMaD)rV%Yv7Ffo?WX<|e|$PAJls)r?HVaOyC(Rko-(~fGCt|Siy z!{OWp&J>UVBm`9e4lpr;#~hBIK^UZxNhGvMTFa`kR`ptFc+zrh^GZ^_u1{HS)=jt5 zd+D*O;cL5C=WEN^KudTVXq0@RoM3!}kl{fr$0L=_G616f>q@(wu5^jzB@21e#=cxK zyPP~}1~KwvA2W6d{Hp|M%W))j(JRQ(NU_Bjb}uZ_FbNwB;fpcG+$lZytqa{E{{X|+ zEvD)gbJ<;_am>)no>?(XlN6DlRSbt~C}25dY@Rbs)2Dm6d+sjK_ibdI+KX4wwRdEe znz1UC5_W^+z5uL1Q@`(BTe^#u+NA8YZ*88O*NE*QNmt0YSB+wU5;&VK9K@b^nRuDnw8+p~SzX=fmXWlpIR$0%ozrc}lrHII z$pzj`#iKGGQ(VzXb9CoXMe3u^qtP|)>XUk_-ug9tG<_3pFjI^hd(V|$miB2)B+^Y? z#>&a7Uq^3ZyYOd)_4^A;%{k_>nP9kCt`>AQ(n$Cy_V5K)8DOg-yo9%uK4riM!?oXr zo;VmYX!Bm%D2dYZO_CXRTaqJbW`(3fZu6>}h~yGVK$I)QHs!h>4QoQgjXzs?*G`$X zq+(eiNSl@nCPrBi9I}QA$f1TnQq7-hMY)eeyPDp6%Q%gjeV!z{b`qmSxqRtgbFd)c zcR31#VCI;Pv$_-gVS>u0-`3rJN$vOG^4g^^P!zY0F^Vx@smxxhI9V!3;5 zY(qWjGS4iR1V=1Z5!=p?%2N?MklbBcNfeS2`O8VUVK@tcpGwuCzr4K~ly4=^oULe< zk}$VXGrE<(3vMA+fFic?owS#tRTWPKC)$vsCNjGUl#Wx*QOWsM( zmhtCNR(IyoQc1<6%pGt`X`|fgI-SLw6U4JdF5p>hjmSdA4>~1|aEyLYHcFCrG8V`* zvPWqio8h@EuOrkiJV6nOY@m)tdn?qplI2iJ;x!paWb&GCCAWoNES4D1wYI;!zSJ!B z32pD~?@lePB(pM0Z8UNir;6x18+mNXCiR#=lfk^=ZK$}O<3pQENk6mVE(mF45&ZJm zTt*N2Np4DcV6cWlKh+lpB;xN2_B zQEndVjNx}U>f85pi)kdK7Ob6`dfnWy)m_)g*6i_fY6L)^+}<%k!$%-rDW;5V+=T39 zVe^7UBb|k`$5*x0Be=NV7%)p_6iX0P-5tbfGq2jC8I0{>julCfOB`}ndS1VMJ&v%x zAe!>n$t)A;mtx7HSy)4bx0c%4-sHQY?|CPdVlf&n-U1Wr3o7>eIs@WVj8L8w&+cab47Fsm3bmGqbu)&YhRUxuweNo%QVRbAq)ALQ`t< zh1I1bsml8M%|*#wu9wlRx*aT@C%l((Sn7YdSY2MzW^JYt#>u$`Rm6WbNdz*Tpetkw z$F3d&mYPDW%Z>h=cW|~q_n!T4Y>8iE)v{zbQ`@8mj(sYd`!^pF= zDFil&2wPMFMG=w%WaNToY_>9RSf~UH*U6s^>@WvQ*zrN*CqV{*-NYo*v~GfbBkaa=;zS95@3!y^);eBNV;g&fZ=z}2ZYQlhDd zk0m;dHBNDhbt-ctl%4rv<15RST+!v_e?fqw&w$5bVNFIW+0v7op{Fu(v?I%RC8smG zNpmEdcU=CzV+68CcWWn;E}Y;#MFi)j@Jvy}IPA$8}OM5qK_f~IBpQC5a z)TdH4B^x-nyXft;+DYEe$?BKfc6K**m+2gDKa&(-d4^mS`$M6Ku|RTBmEJsL{qLI? z$miQsmq*s+wsp6f2>~%i^JP_4lsuv1SqM@ccEsw3D#Ijl8K!tz_BSXm%&w=E372ei z$zo%3&|#6W$9lhY;9I6cbnrYf$XJ=yMPNt^lQNVA7XT0xfHU%iB$BU_o%*7lIUGhPS6p_88#N z;<2|#HnQT{+B=p-Cm2k?S6 zkflN9x$E>>XPnzYuW>Z1AuLLQ6h8G17513d31Lo`rI ze#dbeVP-cr#1kZ#`J~uOYlIM*|a;DYOy`J9;m-8;yveE9( zH}M_hGV7~#rAs7}ZA82=rej-(Tgw14G0Qrlvy5c!EZmZ#Vk`BA>N)(TgqXx{<|y*y zVvHR?;0$t5XE`0KUrO-xrh#N_Rs@^NcadfWMwVi7T1J*F+h?w)*`408`GCefI8^o{8zR z?xkz?dM#|zMncU54+~rFCRrrjWNqrqNNt1x`=tXoAThx`#b;_7jq}ZOEu=9ZXj&*O z{L=78Fo;EhyE#WACHjEa+r~*9tf_Nz8ABv-g$pV_-7H83Rly0!z&%emAcL6R+@$4H z0pz$61a4YD17$;Q8yNlJf(}p8ua*+JciZN+wblOs%fGBQC`&}Fozi`8s!iS9>7wY) zlIKFVlFAF_oW1OEMJ37>^KIq8#F0XNQwUPvkOYSV83wvP3wWLjdG7R^oif?<8<(<~ zrHGySMb*Ce+T!*C3pK6M$`VN-c4a7yGLX~H8orT#> z-j;oo%EJTopY|wT1jQ z(ocF}`zE0Tmh(jtNd8PST}JlTk*uv8PEn$n+U6M}iI6YKUl=@1y^W`fbl(6)Wj(AH z`hB{=3LBYT#(hOo8hyRwes<)y)Fu&G$>h8%70XF*fn4Ub^~f$>D><~Zx{l`aQq?58 zmd;&g1n^u0tvV_oM2m0afl zWR938IODEIy=2F3?~seg$t3z?IL|x}^WLw*l0;5o>CfHB{{VoT@-hb`es%pe=M{B( zwb38WF^sKub<+Fkz5Mt5%g|griWym>EJ@f@sTl3k*RR*p0Nl4Tk~*_w@Ok{Y^y}Nw zs>d@BHlmE@qL6dbo-vMndt;?&L*{}wBRrB6kWL0pe=gm58LXvN%GO%wmv5P@Y2Exu ztG#c3U-CK&Pd!49DM?TU2<&hUFb_St1N}R=JY}vV7M9X5k!;Y#Y^Faj#D|su5L6bz zjoq==IIlmnb|iewfx+p=93FAdf!p4;qmVApcKVaMoM-8ur%s-=#ZmLLrwGYK-E%A1 z_fMwwx_y04>T%^ymU4@By`^myy6pOEfB0_3FB$9XNM==B@xTng=aK*%k;YH39+kIi z;_Y4V>%y!%#c zmhj3{upnpV!r=}{$mam(o_lBUu5v9w!3inzIsi8SKNnAnE)#E=}^z<3S! z9SH-Ikiok99CzUJ%k1R~StX;{ckGj0Hv8;!DaL!rH+|b_?X~USr$P&z8p20o8?*;; zY%yk4Zb$<;!jp`S$Lm$jlO%uzj7%_8xCA)H22}9f&NG4On!hCQJO1WS%19%gnDx(6 zPpRwII0BYEXG)4#;F9_koUlNE$+$Tn1;~u4B;aI_0rk%i>CNi7rPpUBw6)%sUww@u zQAOKGrnkDY@=dM%HMsBWxh<`pP$t>{4i-0+@Brkh26x&y;2ipQs8dGqGl;bvH&#Wl zhIroc7n*3Ni5IFYBM~feu2M-~X+G5xO$Q1!g;e{s2{Z3|E|b zR*~S%KUT8S?e298tulLPnh!eAgpNdJSMxR%A(*!zgZ!Yd!LLTrz8`pFL4l>ex}R8{ zU){$##SvnxG7??pM#m?6j--+la1RY??MX(Qy_X|=sucO$o!0klUe~?by4CBc(MpsQ zZ&os><-3%*d2iXR*JWh8q_kcer)mBgl~uH>+e@h;baw*pEU%HUT}E4WM1@b6D&)T2 zH(*zFXQ>-^j6frl31d{);&d#nlC07l!E#3MepDF7Gg^Ki_0+xFm{|`rkkaSjOi*~!f7d8w&OU-+ud$UthJ1{TVGNq3b<*)qmru@ z++LQFYew8uZrzu<;_Q>w+nBmurENBlnl`g%b8#)C?=7A4ND^yRkRr4Q#l(_{0*93d zDhx}zoM&5afo^1i0(AIq6s$&MSl7;V=*y6@wCG0JnL&&=IAU^ZHct&}Gs$!Yn-$E@ z<$Z~T%Oh}D%G2U90%vGYrLe?;z#7k&!MdBTnJtL5c;snr1S(Y{T!Q!qd2QUgNxCo@ ziQA3_E`;b!s&bTJbvZ>i`#Cm}dMCBEO=&B&zPl>0s~gQl%G|M(w3KZ0e)7@vZYlFE z&c5SHw3Et`3*|+CG>rz=c_#r%?n0rM2)B8z#Es~zGC}4&CfCDvHsERk_AAS&E)d$u z44Q?6jcj5l=2(R5XwrG4z_NL6N=k45u0vFhQ_`lexJd~KBDAqYB$DdxC5?~Sq)?$F zhX8Jr7%E;*v|*WOA{ktkKP|Gc#l6MR2+KNv)$5 zQe3gbPMt|KqM;smw|h9rHD%Y{y_W7>vzwG6=IF+8O7e1-B$C$BRxCz=K9&SO%neAMboBqnW2g=J%j|SD!j3lV(yzuW;ErB?KsVSEEqc|tc*9>~}Vg{DqQ?iWQSgZhmBx0w`MF0)^knATQ zk&-!^W?Q6JU6My3J7ohZSD-!pI&eYiJv~|#>CT*LQ>_eDIs4I^CkZP!{5Pk4Qq`%b z$z7)%4hqy}r6^95p*XurGmMqmcIHZ3#pu^7l6q>cOQ(2>;`LTrInw0`A)vW|?IqiT z)hCWOR#DSvaMqX`JEZKX-J)A-h<^5h5&AEcz%TEJc4uI zy;WPet;=kc*gF%6A9m7mNE?X&5_)huo;q^!+DQ=ebjcmyc?ocjx-?L73xmkO^$U*M zk0-FQ(}t&{z5Se#y~UX^>K2EGTmn*9hXkYGVUI#W^WDyL;FFY7ij56m{MQKTSk;4vI{jJ_C$dey4crEB{+&BB#8bmZcxsLIpQ{MYr`-IOtt z!$tcjQ>Ri+(wrd~PH{;jr7D+NT-cj-Q^-r+Tvp>ES^A3YU; zjxJ&nY~Ibh;1*1iUUnjiqcwO_bXKZ$B%@B8As$sU=%aJ8jZbMAH7P2R z-VjbxsVO&j@}!|>yGga?SX8)lQ>43#Eu5me^dE62)%i<3SLUBo=08Rv09m_$8~6(ll*oT(G;jlG4gZ zg0ftOW`wTrF&GD(;E6$O6$(|j86lQi8`rj5wlYNfjm4>NDf(?JtQ!Cy;ZnyO_2RLO zD7iV)ojFOVH7K<;%Qa@M?yqYn@_m_dn@K{XW|DT~YnAgw-8)|IR_&|TOX*|S{5!10 zbE(}M>#1dic%;*k5VFS{wx$+{!5WaS7-bj;6+*8oz^=N{wH*Q(E-g|xod!{0o_YM+ zb!?@qt97;5vXk=wLKPSw8u1wAitZbr(z4BPIJ=2hOKUhFtjecocE};X+6ZHVis}3@ zrueE$2_rYsUBLr|ifQG5q@H$mg;$v+47&>vhR7ra0~O}f!of~byb_X(Wf@r~XR^{i zK4jjvPehK$SCfiONwnKdUrX6uPiF44)p}olp)_xbQ%Ne3@20*b(Ex<`*kn*ue zOKce}w8Il$@ke-*XF5l1HPHYHTv%m8#z@~Jr|cmQOP$sYXh*U7N; zBhLzON?WMvw|cAHr`>68BNKyytCa^JW3_81#F^4qq)WAJn@oywBrK;O?p*L2s0>N&2*rGJFNq!?NsdX- z;2?`>VEOs73obAS!NVM6`ej#Lo+K9t^2QwG#N-AzILQQ@aybEs#tsH{jtS%x9j^%O zW$wi$<)ZUVZjP_*IqI(LwRUz((|xwLnf8=_5@lC)dDrG_?gfwT%K~@+k^tkLMtwOt zk^D(!$}@n#j1oylPw#GAg2Rk2P;v+W=Dr+H7hPcru_S%$oQz~-MtbM444~)Iv|#a^ z@sM6dXz)mo1N*kf1!P^v1EB?S2p-t3TAVdWt9v+hR8@K0v$0m;ri4QQ{ARz+14s2R^JKqRm5P2p zUl!eAWZjb3!|odyPky=2QR{#>6=^(Qc0E**2phMr7{TE1F~&K@bI*PXoHb7RMlrU! z+jRXew{x;Nv)1~j)js;|eY}slAo0!>SM5=b_}$w%$@M4l=C((UfhZPb{t}89Wh+hIASu@ zDBbAnmuGE1Q%L64eOGONE3Vi4&%95LNJd|^CP?{4c^ijNJN-u(=BJOxC0B{V5;()~ z#{-@*j1HXVuodvC_~vp{w5%Kq6)%iqi190o@lbnz{4l&!M za;_Ij+|XLxd@9d>Q)in+rqg{oufOv?`nK__JSwd?QdPcu?l~m#2RO$h^vUbj6?WIg z7%V*VByJhJ!sB{2-~u87eodsYW#DZbftvV245A62 z@$JeK3pqH>GT6!LK{+@*fx!o!J6A1U7i*cu5l!FSYu&Q*w|i-|&8gE?Z1b>c^g6fKG5gJo*gdIp&<+Du#Xb(@0t2*>s5;lq4gdSKW{cDIvBJaskNo_@`3%p38Kz z2X;cf{z;R8AvzV9Wy+iHv0fE;g>* z@tk1q9vZ6Q8^+D0Z4%Wjc2A|(o}@g=l5bUO+V|JxYis88{13U)#Q;OOt^f?c0Pm7X z0G-DtZ`}t60GhI%EJCY`gaok%l1T%Cat7X@_s1Vv_-%e8N;cx?$c@e$f>@Qq2Hpn6 z!2&(G1e3Uq2D*GnE&{ZHSwZT-c)%oao=$q>1pZVm8LJePle>Rr`gFF5-_?GC{?n(b zPR`GJ>(_tlvG&A%DMN-6sVG2VIUPXf>7ID#Gt)JE_@od5&mTp)gKR9JzcqCx)j+yJ6aaWt-X4O&V1^GzE?B^SBLCy|&$m2ehFNUi*J43GR zZMF1Ezu+a9)8$sFznzkI*Zj}1M~c|6Log#foE&8I`Fr&1-+*|jBk@^gU?+{S=-}XE zkO1q>GCg_kUl+siEJ(TY5es>sfaH=@*;IhR8FPT=3fLro%m8C5d_$EJDLRk|LzY~O z@=5uzk&Nd(_^Ou;)wjcL*H*uMmY;^daDQo2zr>&4>C=4?_Gs}}%1cbS$Q@gO)2;_h zcJ&`hnS4wMTwEv}GR@O(IT`i+G1|T{9}z(VeC%>YK4tVI;|aR5OA($qWE0GIBe2$6ENsek2m-6P>*O01y~H7a?iBSpP54gxMMt?2VOCPGCjpyUlS>sRu?KZp;g@31OfoS(j&vJzA*CO|yE&fg{zB#<$cABP-c6%DV%#xpo+TlcVhs#p!IK4ZA&?+g$D89hC! zR}JDCZ9%k`M4k0l(P^U9dFT%@r{7lg)qZzA#lP`N#GYr`VaT(QvZbP08Nbt~xZrG_!6 z>d-|aqsKIth6t`9vbIPin3yLqMKS^zS};iEynFF?#l9SpTOBUS&fCK9S;uK@bz-*n zT9&1KbjNkJpJyKUw7ox0i5T48UVV&jo+#mGaKLeA;_i%sy}%|Wibi7&3^ z2xKvmlPjcX>=y-=GOPeNW0lIclP|@&JV5%_{3Hu=3{3#PfPJv-cLbrbflP6c9_2>` zOS6V>!9tAv))Ryzohq1|H7G(5jCmzLZ7P$KSE(2&+A@XGgM7-|(s8<0@M~vE(}gOt zl&^cG$fBa2j#6IomabN_ZqdE3ey8@0)bBOD8%r$OWVbfaUS9ZhZZ%PFs6M3el(HBcMBiyiCs1Mt=5!Cs$|Z8hi{+42mks7I!S(Nz>B8Kot6c&T#BPm0aET|3?1M$_{?wNXXFi}r3x&Qa3$l1?_iTkF?P zEj>Q_;~&MJ6I#ijN#h-3`yH)fmUV+!o(SYcDA7V5IhI6$@ES*yEH0{7Cw436?-Wm| zT2A(N3gSt^-X-4EyeH;$5`C=o61!S5LKId-8Qr*mYY$y%652b()8@B?M9VeXpEfDUJO2Q5sL$m@7_nTl43o&l zE2{@aG-_Iv3KZ!{wxbwAoaH?&&1l6vHgB1?vQgCL#Z>l@PIaozanUy^N-8S-Tb8;t zZ4ysMx_*D+kBYuA_+#N85O~W*@f^A>_K&38J)6aIKKsk#6QzZ$umk1X`PU!>w~#P$ zz!m48$=z1|>s6lOYx~qXj=6U}t*zWn<)_sz?&kYN<<-o~lXY=4g`R1qW_Oe4C79RN zpS5SYbb4%?iXobMFm+Da>xSw3WwZ<^}Y((UNiPWD#N#}En}DJ^hkE+9lMq8+4-qD=3~ zwh0?Z1TIFU)S7?xe3sCpmb!zMl1U;8(7NQRG>!L_5GXOoqvj)NJ4JJ?ePtmMi-s){ zg#oY>o`l5vnP%yR1s7;ur#YyF3oDzVJy=&&TSGNv$&e5XG@B|t(L5zu&w z7HaP4Y`+V9`u9CaRMJaVbnkB^w?}pB*UbCJ_Ez|VsOtJorSR)f)TGp-(Na7A01De) z+{r8!`Z}_~d8S)OGck(R(WZ`DYh_Ulybv%@pa6c&g4zhBX)U6RO+S@yBS3@70diFn zVB3<++lux1K|C#fIs7g0R-xff9rznrOO$|r!a--E&H*Zqr)zSJ7UpRj51I%?@STYR z8v(}|AH3R6h9AN<>vwx^Z>(CfK|9}h=6h$izEaUk3&$4x;xeIpzmTBaATBHEuo$Sr z4aqNhr8~kfR*Rfouu*MUHFlld+qU;@csQyvop&VpVJ=xpPVGgc)4W^JK2-M6UhQa~ zGTsl@VZ_%qXpj4_majFtT@{uTxrN23l+ES5QpU>SJ%Ah%8zQP)=#vX9l~akPFYl=E;lw*0f&F0i&wdlcNSN+V3oGJSsFXk zjgIxRoFhRjh@UaH^E|_yfeZY#^jmmm!&=^k#@1G~y^ckONp2xfV!e@a8WdIxW5Nf> zatB=Gapzj5hpJuA{{RTow{ZB5;>tCeE4vF~vO=+g5^k^;Xf{HEVJ@ zU52G)rpI-0WofBtXUad?Hl-iSB#+)mBPQfDQf*mLP?&*cAY!z9U8%jwSw5>A+N^_5 zXmtH<)R`_VtyR>;X>mL4dDb${VMb?kQs5}80GjTPaV>?e7SeYuHlIJ4CZBS#t23#Q z7jz-^@a(ELg~;kFxX~^p)-2Z2%SyL)MQL8d%w<@H=0efP(MQ2$I~1??iDGaoSCHkO^zl27}$JXQ4D zGi>^e+>*$)(mP(*q-<_xiKJzUc$o%6Z3@kj3W0&p3a?}0dF=$cX6YqKkid&Gx&6-4 zs;*p+uDJ|~Nac2n1IMRp9uT{_wz{~|ZH$-E`HgjAvZ_dYr(+}`TLApw(mmTo;0eOw zxOsGY3u~Ke9a2FYrZ~~Xx)|OWi3=j!v+gZ4O_I_kV{)efbGURl!PJ9pRbtfb1mk$w zCYn~eaZlcoX|-)7Wo)Avdnqd_Q%)AB?`eEVrzZJ*>wBt6sI}9ZT#;oR`jc}8_AwN< zfm>q6#n)`@2*8!_j2!}yz^?}Yk4a0U)pSAOd#ymnboQ%m5*BD2TgJO1Ws3;vs}NOS zRY59$go1c`t9Z1_$?deu@v5b&r=H$hq_!L-0e!&=8lo&P1;v_T`S#NjF8V(3owZ^L&UF zPdfL`f`2vw3nCS-S^@=E=em@TeYSSFy;&nF~v3(Ux#kfdmz!Dw2fa z?*^jk#l}&RoE4n8p#9{MZd}Qw?zpzDheD#FswWlBxxJL7IJme;zjo72MZRTa8S8Cr zB%ArB-&L~FFXfuv#@+AROLe=^wc7@>xe@ACU`I8yO$ZFTWL6Dtx#4WXFPAh=8q?8= zwv%ZFtEijZQpzCLcfllz{_a&G2Mm_#Sd}v6(K8hBt1#ZGO?@-sZw_0uFlvPo;^9$4 zmWn0vR&@o41hX_M?!mu$Q~{OfE5>!t2y2>syt3Nr5j5*?(p$$il&ZH7O)Bwf>vz7= zdt@XRb+}ed@swTL*Ebo`pEW9)Rj8+TcA@*JMJYz@Nh@W(P|22xBqXJklv=hINK} z8RB5_nKzfYl*XQ%C!ebNZd>{p>n92WL4+^Wc9EYL|CfQ~M9Ge-MCVr}J}5+-Kb zENv>b#sRkGzLg}h;724O$cb7-Z+xK1CvbofJ1iYSqieC@y zB9W$w~CKVhtGtN&^rHVad;?{?b=6uZ^urxRU5gCDTv1{_)t7 z3!x=ZLlDJZX#^^OH&+SpIW3do*MjdM4#^&)b>zf|kamFj=b2)oXE6SzJr5NB_x=&Xu zY_FuXy`!&7>aC@{tiC?aA{d96_Ie}E#qk_00bZ-=HzD;e@Y2wWvALatnpdfh$3c>Z_AcvV8C@|EJjZq4@&d7 zJW&GM+9l#Cp6Wj=tV!mzoTb2HA^A4sD1G2CE5QnJp8o(&m+bMFbqPh)iwK(2P_&52 z8!pu|M>3aISrl&a%H>O79it|`)hcN&RNCghDpz{9c9Z4NYt6gf$)7JTXxitpcCv3v z*)243*KN{P*6T)e=zM}Mqeo!4AfO~|CvPP|%He@5P66siTJJoud!aSL6_o=axCE&Q zzjnteeMn#l#t%6eTJzrx>QLAv#22ixuBRf!3rye$6mBUR2MVEFa7OHjHu7uH{4;wN zpK$itm9YNKl^!`ZVo@qFC0R!sO78Sw#z8r(F%>FCE>Nc1kGztzbBccTv`x0UZlB(3 zLKNGy>LjF`Z>ms}zr^-y&EEU7ik8SR#v}(g#t9*Ec);NE$;NY>p7i*NLkq_>vovIU zrY)og$UB)Ft}}vL1Fv(M^nGtava_~}P}8nNwz52cha=5_a%7CUa=;kMVSqV2e5a=o zbe>sV#|5xab^c&9%O_PWmH?xI{%Nh}bUfcM{kyfsRkg6fXd9GwoE}#?O=G zJOEAx(l9}Aa53&l7(Sd<-Q~Q`mV!Sp1D6T>IXp4QA1-hXIR~f!^NVw*>XET!vXH4= z?4gmBg8lQ2z=MT2A4AmQyQ1Rkxsuan)&BrHws1-^clTTLi)k(V*JCeGx3<(sX=IyE znkbmbEFZf`fl{!?AzWo1LV+DJLB}{Iuyid&XPK;SqmtdCU4iD#`Ec?m+D=QZ7k1;v z%(*!=zSeWxm3_d*nL?5rZADgKK?9w;Kvlsx!OzRhYYz`j*OTgLs7A&Zq+5F_t@q`n zCg{Cb~EBS7U;m?2~Hk+32>jcH2e1oYvUUywl!D zztP=hNWsGH2+SLYByrQ6j!s9Yu2Mwu96u;xBXR(8amIQK0DJMqb6ruA`%1f5^&1DY zvbv5oisCs$wzl)^0z{rhR3J$pXATso-GX=qq0}toon5x#;~yx(W%58hS#p@<5DDql zh)G5AyDn=q)7^I6>bj)w*1AJ9Y8o! zf;VR!7;Pj2oSar&%&1+i85uXSiDS;}Du9d-f=2SI&N`Em>N<%ud$=KvR@hmA+=FankTR6+~#qe+Sx62 ze~NwVlq}D79vfbzK?2`CdKN_kU=XQ1QrJmv+fngCddg<=*W( zR+-|EM`d>2X^@bvB%J1As5u@~rNDWfH~`4_p)-9iLTGn@H_`TSo_U8 zcF|ka*?(3#`1vH`Ve}aJzMzBC+aHx*j%hFk_W5`i3OMJFxxoCry4N#hsxzv)&jW+d z0->8Z`G_E3`yX&eHMth7V~y8jG8QKcWJMsJfC5H%>+jy8aFy+S7t80WG=$=n?dAO~ zO$E6`;ilNl(N5fR*PH?g9-YrV)~)69W(Y3uU*3Q}Ck>hXTBW!Bp3c-Zb# z4VK_d(cS^tr2{iD0341m1_p881l6G~o`fmXVUf0$+H$O??v>%OmBtC@BoW&clvx}r zB*;cd#_$^_9gYYC9fv{JrAn|oxMjxj*x!-RV*oaI>5h94FRwX@EBx@VfCEQ1Khi6fRdeD!ty`jSg9MI7yK zm=^iB7Tt#3j2<``%}f+j(yMnC?adi-wY9FTs`S54GNk1w-kV&}N!n4m*R$C^nx*Tp zLi5MEzt5%V&3|beu$YqaTgl!y)zqEqZMkA+UB_a|vLNH-vhrScltlXPZ9WU{v{qD({7{*0)3iz!kAf3R7nlU zM!`eSF=Q%9E074iY2v>U8PW@VV_KE3C22Dn*}h_uV#^FhTS+5B6h&h)C>yqi<2bK5 z{?F85Kpid`FajzwJI0E*AdSSLs^oTtCT$fT~X7<wvU`eEx zf7zmWHUglANQ*EdZfnRPvy~uqluRIe1Wm^ZxC#L2jAJ9Vc?P`$!umwoz0?*kNNp8~ z{p3o^yJGHPAW%1kMI`mzoM7grreBAI8_o)224bG&07D%HCNd=W9#wZk490 z-rmM$NY`XiIvM1SQ^ratcDFJfRh&k@DCafaY4?^=+RvoxdVG4um#}6V$fCG=U_tVo zW0!UvQw3fS&yAxT3h`>vp-oCusYMTI+t6wK2^&fD8;*8_h|X=PxzBP)R&Ajog(EmS!9)(@Vu{Vmjs`)+nX6JB#bWL zfCj@33YEw`hLP|N^HaOfJauZVt4VvT?VrQORi97No=CR~p#f515UMLgmnK3BJCRS!ue2Qw+9_@e&Sbib$s7#G&u?>U2G>D6R~}O`GOl9|r{*CIbhq)B!-%( zRGgEOij11~qbSPhSy{8yrAn1ps8ySGYH^$zX*k*Gbdz#dx@qrsZl3XF;ol5s>2GPO zyc0Y~zi7B)9$sY%%@hlaIxcpScOArqAwUDUwea_bBeaKH^Q5tk?&8ugEvLj$eXZlS zgsfz;hA%Rg4j5x`0B}be;5}2qUl(j|n^W)!)27p-Z9jbWGg|r3NWNxlgT#d*VJ_wJ z)C3F{Ul)s` zn7WdNBJix`%`~dUP~@6&Npi`>Ug=wxM3&nhK|-bvmNKN^15+0kS5tst`(3lx+q6;0Wn2{oUpZA`BjzEGJ4QYf@otN&Y5M-9 zsc5<(gTuF1Mpe?`fXt_Js;LNE@7}ezn zC`r0xW;-{ zHFfX?CBA{jEN2rOC}3+V=Mv zX{FZ5KV1(hSzT!-$;l?PvwW@j``3$adtGXLYh`B^n>E{cNhB9BY-meiZ~;@0da>+I zOLjdgbHk}>rvBn4SS6Adf$aeyjAQ0fLmZw|VB;zW9E$BcW$?FM@U7a%b!#pCwCvwz zzOsgEh{#TM&XA)tQXnHDMG8sE6I?C7h3@XI7UIea<&^;7Kp($B8{@a1Y=uVV1ww3W zg&~)cI(lQ+g?bp8Dy=HflqVGVqbRty7PNZk(@ytMl6OsYeq`xYqftV1++15+ty$`x zx3f)pHnmoJrGa@9&mj`S<$%mpwgqlaUw#1~`}OTqUrt0&`066QAKLPzkcdMpq zjCRRsaXT?8s`j$Rck~Js<5Ec=ouFqu0R&Y!^eeR`C$+n?b;)Ix+GvVr=EEsK!#T*@ z2g`=e(x$ie)b?DBt<~1r>uziGT{`Y%?54L)-T7s|-DI!l)8=`+wvyZ(sVtBI^JXuI?$&O2lkPPgD5<3j+GDtsoR0d)fcF;+{=QY{?0Aa{U zaOj~%TXDfqG0sm;Z~*+ct5NAYKmthlvA||1K^WQr z89J7pDAsMZUoUql8gS4HPpdNAuF{NWB~5pm98Qk8b*DwfZb0# zgV=izdh_egy0m|$@D z*L+1v>)uVOb!8QAhn2xM7UgxTi+4)aJ$xQ2t`%C1IuiFvQQnk6XO(*uW zM{}w8uI?@K!7bLSbtFbOP$K=23otD;$|8xm836gfZsQpw)-Arhb7>LPb&Fej3u&e{ z)~v*!yShY1c%X^fd3~&m>=>%<9AFCNJR9Rn4O>li*EA`u(RB-5C~LkRj`I5A!&1LX ziEW=z((L1s?&D4o+D^0FHN1%n?A%qQk96M_J^^^^Rk`qto+8$?`z=1|?VG^bu8lw0 z68=q9B1Vl~_*zMAsE`pPx4RHDO|{4h%1(Gc?CKS#m%?ueUM(qoW^#2Z!ZGK)HF?6d zqVFV}YCpgd(9A&C1m7py2QBtFBo)B-^un#ixxv*3hMm zlH5ZfC8h)_6$j?n`9C&!!Q9_YYtS_N+iTE@Cb+g}lpnK+9T#@se8pjcS#VWON`S`IT>2$d>&xe#pTV6T7*jkliLX{t)?Gf1++D|#nZ)<)V*R(@q+L|eb z@+sv(nHJ^~6!TlU%7ut5Oh!de6oh3bA*#Y!>bi8Xe_=}cMZ~N;_6)_YL`}I%&CHwf z#0bgv#}#W;@pb;Q9G2RN{?Tm`RZEN8P$UZ}hBuN4Hsr}FAyV-i$O-$n+A8HblAIkC zPIS~$sTXxoXws5z++5RZmOHJk`ezu%F_Njx8Q$@dvxBov%`bY%CY!TP_ja|8EX?te z!MFq#91QW)9CycjV?TvNFOML;Re>$)26{Ng3Fqa&8RzR=HoU8J* ztW(qyb{?B@bH`(x{c}}h)0!6A7%~C_usPh^5=J;Yj-w~8PC=+zCPBI*yaUt@2dKwF zIp}(RRC2}iTKOx9PH}0sB)b0qz_T_Ep&-xi7@T~kBw%`Eb~qXRDif>E7$I4S?9B{PI7VyBpi>g*BGeeU&|J} z{{YD^^EKy`lC{?UPhU6rn^0@Afrnz{NL+E1AHs4mpYim?SvtWdmN^-3atHupjyNZQ z&!uvbBZ5k+5(Zd>I0LqE#y=0Jz^9`gK@19jaodyIw>|s&`pcsUE2ziP%GcY+}4MqCXH6+@eVo@<7~5gU`wd>6{#n)ou?FOM(o{rvQwxAPkI>dgBKf>^%-~ z!^o1k`4f`Bll46gN9uhALjH2~$T{R~?acc#D-Q>}QuIh_w3eyAxv%(r zk57xl(v`wpGP0kT5*TA63<==$BcbEINTrj-Geqj%apYhVfJrD~8B`nl{DzCD!#D>($~!QZoE$mE z?BpJVab6ea&C4iKqmXhk#QorMdlEV7NY6@|9YN4-JC9yDEy)-kLD+QXwkw{dSBIVN zO@0^oe!3e&9Z_iH?4FzcDS7GC_DlZ&5{t~bGe;)i2|O*l3k=1Ob~EK%5l}yo>Y#2WaFsDDXpo@ zSf)q^f><}r*8~6x{W3?rWU|;o%aZY1UFwzp08No=7UY}ex60q2;?g}Jc-ryfgj(Ii zi1LFko(%5_oS77CWF;F2tG5O+3CRZsPEQ-j3YL}Fs*U*!#WwW;Ny#GvIr{onh_s$- z4=z=Pd@upn07G>-I9_&;4tOI2wPc-2`qE~Ob~ps6h&Jr0$;c~}JRIbldLGrhFf^O^ zW4^j8y<5KDEexfKslDa*>23V~059@BhKI+yV)OpeQW6F(4&A$0fEWXuZa5rs&(kme z0EGAzKj}@hkC!aN2Lu+$YyfgN^#G4k^Rw!+I_-98A~`D_7hpSs0H{yO6lWM2!0Ayf z^RYV}_Tc=vVTR*4&N%lKy31(p;FI5FZ!InPY2;+_bLGJG$ZETQAoa82Y z0!{`!!TE6NE^thTIV*yG=m2uS_Rr(%)|%S1`M{8?1u7X>jEr>1=rN3gkAAeCQ$kj1 z3jG_5ZTSsjY9y~GYdvoIpHVl&Dd8D6X|U%YvgL^!F(U+?hm-HqID!5tTmW`Xtajjh z!M7fA7trzVf&j)3KQEnD;9yBJYy=D)%)If&1~H8H#UpB&!mNQ$IUPY?d~_d?{03>P zuMD2BjGg+$Z?%(M1uSJpw5*@^o&Nwn{{ZBDIDRZ@O&K0(GoafV78_-Vj#Zlebpok<9O-Q zXyj+^_Z7{~mlDp!B=Uot5%&Q-+C~@$AH%ru-vIOK(xn?EWo4qeUGKfWA2ZIKNnYu< z(b=`-^Yt!&YFxOxX{10*rLCbv0IUU7e6=GX-HNl5j45-0fH8r2s$EAo*uW;xUI)W( zBxN&^mFba!I3G&e7Fuj}@*BJR$gfph?Zvupg@GGXO8MNakO|s0lp%p^nu^K~wMpcs z+3k|^Xr5=nLN><6Nn~aULpUEW#^+)b0#7{`-J)yu-Ji>r$TLD=TG=c`eQ-RSwA9g)OyIg;HD4p5%;IJuQ~6Wi&S0 zg~K((vB;sKP_HqKo-Z^hR=~=9$2)Qx9*&~9VKn!@iiMeHk-FwCrZ$K(UZKN!^_Le;_Y_rFNX5dOQgFVQ!R{5zs-cS zlY){lO|JRm7ZL3Y!x>?Wo_%pay4CFx9X>{m^Fb)c&hh^K!J8XQ#2u2`@%#4uv^Qiy{*t5XPb3zrmf3IZH=H!aES|+19!>t-0@VSD5)-bkxp@> ztm;`O??ERSSy`yJqiIIZWiZ23l9P*ZjrnCa?!hfR*jEV$hUEn)ZsZUia^4Gz}FfZhpkWH3UiV&OE&2U~s zWB2XgcotWbqpPmn!NP(M+#k0Kz@HhkEh;TCPq15fQYDDo*}b)`;@s+Yw@Yzm{#wB^ zLvJ)G^H46pKmZK3f0}=>!KTY<#x?S_0WaEO5urwNhC-3`F+K_zR1iyq z1n&U<07sv*4xQpn8{n_Q1o54z)b+bfCFX|8S<78pX{|KVX;#xLtPE3#q-kS}5E>(H z2PXqr)SMvPTe5O)3RYA1TT8N)_LFOt?#$=I$J$CtOIFfO*J*QWt4~dKN%Xzd)A~ci zKMOo9;u}GErCUki{dZc^A-Iy`K#IZ`Ew3VWNTRv5xU{*3E&f^=TG1_Mo)#I9G2LD> z;vExP@D$P7&0z)hi*qPzU1HuD15GZ+l3PY;8dcu0td1kw^OOyZs#N_e;m5wcw~AHM zua{B1Ym1qzV6~D`5R%ziXA}+C%QzAqF)-&ALy9UjY0^r}(c?w3EckX*Q2#p?2O56bG}I+X*a3Z_|7=}gYhqfrPDMPvb#%bX#UQ(cXtUKvIqs7 zFC>zvXz>aLQ7MfuWGExr%)w6`@h9K}9~P`MO=dk|^v!oq(S@y!qZDG|+Um*DHiq9* zwE?AM1)fOQLhlO5!Ejp#zYD~Xrzrh)ylPRYD%9mUM)7NvDtC-v<7lSi7Lt;JjGr>p z<*k&tC+umsRDy)zX*H^Mm7g{5B$Tz2yqmSJ%Krc=BxyAWF134Gi*u__GdoPYvJb*Ba96E+EowJUG)|rmZ?WB<`U_hNnC&l88CXT;?U7}SvZ;8P z>(#~a9uF#w3|#T_rArZYh2>JIIjFVI8A2MWa7jbj*+*(}w6t7wa;li`X-Devgz4GT z=1E2^uXb^pmAReo$i3xfB-+sYkv1Bpg?Q~fxVJEnWsY=Z6O8TN;h3v0KnFm1TmnUQ zc2ntBR`LCpPm(=IyFBnj+wJB?>m+H7q58WN`44#Wn*B%dm;4h?$C};cyuKOuli{oQ zAPSc<_?pJ|NWNQg%jUBsjf+`MBitBlnnq@K+$-ik+F$laPuZhh@J5{eHq*RB{xH*| zx{q{AXE@b#_?qKUx6>?<7VhgyNK`yGW)t$UR>sqhM+L>%7G*p=96ml0##U3DXj6rL zbm>Q$qNt@!MJqeT?aE0$RQYw_#AG>+6;zb)?a-#|>P}FzQg(}rQf~bk(J!^5y7}50 zSGm$I&{)NHZ0BKP^UG=p%SIGoh+qg(`GwC+I*hujYHM;X3{gmyG1*6_tgGfcZE$97t09k%c39Y9 zq3vqajA+VK(x~K=6st}Yqs?}?Z#t1&(s7J$?^?|B78-bl;Tm%Gk&K&zi*3f7T;7R0 zwHUW#wbdlnApK5!HPef(=0dF!!0#g}K;@8IlG2!!c1om%A6kFHt?|c*BZo_q;g`g_8_iM_ zp3?f?zc0pjbQ4^#rZ3`socgDsbtQnXi15@}b{t3D9_u_`Buju-3gKacxe-B>S z!*Qti;m3yj%iTuK*HX4?TU)aY)$g5Yd2U+oPJ-sjD}yDxldSN~8hAObWlJxls=}@s zG?uld>(Gqp^GeEUDywZudO0NRHEAtXy}Y{%^~#M__R6Kdbfr$GB-~?n2IUJS82yPp zR~K~MoL9xynnj)WnL1sG*3q*S&6BaVp5{P8!EwCF1i4bpyI_$eRLkx-IfW(B^&K+$ z)!s?1qmwrBG>-x^k>P+7179Fn2P&L;@A8W)Aq6bp8PMZc$-}C-k0NF z32Cv7LsYo%cBx^i&7|2{koOmQhLiSzt39o%=IY{mD=FiK-U(*7XyJ|BekQQ-MwfKY zG8z=S8;7QMWoZwyLZ0@;1m36@V=!a7S_Vf z_fyo7En^Wa#Bsp#`Bw<#*4u}wqbcAVaOEEb+0@nz(UtlQwXhf2A;R%dKvE^viODvG;;s1?S1 zZ?}cKL`B@bMZ2xDEU_r^%;N?<;vhmOlWM$#0E$awCgL>u%rP8Ggi)R2PX|FpX}x1Q z)n|6q{pR_e$)&84dK|K$Dj7BR(r zk@Lk9I1Wfz1cz}98B{RckQW?cl(XrV2$9@c%XFS(kHF#zv*zXJq@>;2cD$n%XJ>gO&CHuoK31(dbEjo`Rr(~~v#8>djAWCvT>a&HrF&WG z(y!s&MYVOfi^Wn{+Uf9IxwN^CIqjJe65dnHvQHxcAu8C&0f4~lJrBd)BU`k1u1jJG zSrTa3io6QgfsRSXn2W~Jxxqcnc&?p&JQrnd<=Jpy{{TsaK$i+ifUP`R(4zoMd*s2# zy>*b?2$EB8C;=52!gJ@Wg@B0Q;hrKhwDO_JQG;Evijr%enLT57s$FEYZDzsg+Nvm6#JKe2Yz4g`oG_03af=Ka}0ogP1GUGm5XE;{u%Z-HRH~OKKcgbWO)HRLB069^(JPyo4tZbNKz>FUa_^?14D~CTKd12(? zV<2FM#zLVT9N;L&Ok%xK8DQ1yi`lw~SOIkqI9rIo%I_mMJHoUwF#s}x7!22yh^IU} zy}bzX)r$ADv}(ioTiL(md*4TG8R+5aLcCQf(r%RFrJdb5t1fjNR{FJVlhaEal%jf=Jws?2L@%08aXY=QW?uIP@ulh!#PsMu<6sw3PMyxBdWsTqmUBi zB#f~emQq85(TinC1RCCkCN<)nq^fLbco1Tl>Hid|z+Rv=p$AmnERgPu<(o()n<$Y6JgpO=hzi~tR==V)Fw zg2yL-56i*zyKL;L>pQmlrb$3-?j&TG{ZMTru^_6(6 zx!Mmn-L&#R?~d3mYsYulz5PCCB(&w8+TTr;wDR20)I38y#*?a9Tv)Z`nnu>v(}g53 zkv0)=!BsKJSy7NiLWKt|3!Y(oPYgOjMW|a!`n8q07SRQfrkKK}M09Q2zj%ns$tLnk zFXPbYdX>If0)<1e&ItscGa-lo@ItWQ^f<^k#dz<;-AC-Y&YGy`8sZsbkpjMCEL0bj zkr-h?AO|31;B~E`P1J6SPCsfgPiB{Ad#i8TbZ0t|f>o}hugfSkqfPI1t@>%{w*6;> z{v_yrDr0T-h0`@?q-f^R?})a#%CS)-3o#~W-)n6v(Sr=&fIGSDqM9=cGpcnUFh>kn zusfG-PI&56j-#%AUb?i=b^S4|Ztbl_%g9#VSA}D^ib#lLVIWY*!JL$Bz<}8uYopVA zapE5eTU%M(*-NeI_L~LcK&JZoC=d@Y31ahQeUX9{NjPz}u-U9}lCyejL< zD`{k zIn~r(f&d(x4u4X0NP?xpPORINzy+TpJ6mYVmE<{K z0|s0Zitdd0^u6xY_3FP5O}6{^We!WUwO6v%$vfSCo=>sF>zYF9)=Bnr9C!9|dC5Z^_+0&6vr`F@%#{RO0T{p4uz5=GC8D^f$(>XrL|_ z?Eq&H^MQ==g#KioQfRIro*bOuoSdI6j!t{E`q5SFA^!kBKQI1Bk84-{e6Rcl zf8>3%v)i5uU?v838CrRlrR|Kl#&lakXUih@OdQgIIevc zShtr6x5dpa&q@=v9 zFVAnkOW1LgTYS-J-+fohOD&C2Z*w0RLI?l_+yTMQQdBpCFA*d=))u)gcipg{-2iBw6Vxb2Ve;pIVDFK;A7l$=s!B= zlakU)=WqBnxzPy4ttIHMw_jiQCF^^uc?gV<8)}lJI3M0Q%J=644`Ek=L%a;ATwst+ zdUJqAFgeFHUO27U!@9TgU)%#;;ca>)FsIVMa~Ay1yFd$B(e4A zGEY9Wh?b0}FwFS`k}^hk;{!aNJw0mBlIq=axG*dU&UgfL`B)#ObAgO|X5)UT-RXDp z_4)q*nW~kyi;cB*{{Vrx(#LW*4$L#gO0gVv%I6!q93FkMSJv-dWnnt40U0VHrL#=}L;TeB=SOh8+kRA_Aax>Sia5@^ix|5JM05+bBoadm< zdSvsAk-_QGxqEBK-H2snJ%J#CHxMv!k;pmhJ-DqOF-gWr<*-zO2V9fE7{MfGJmaNv zIIFwITi)$9{WSUCb8c(e($mlWA47aGb@gYe<=p#P}nU0|FSHfq@6{#xw89tszdAc_-JE zxcu5y{*e-uM7E1p(&<0V>*@F%aJ{kEr{u#hIOOLCI5@@*KvB;GsZBtDXs?3;B z3BwK>wh6}va0fU!#s^yDW3-tRmHA1*1A;ToFfo8}jAR^OW2R~*w!C6;+s90Tq^Rd0 zYhZ#Yq->p~WeK%Vee435{IQ-r>z1_%Nm*3Ao3hniHS9q8oD}_~fWR15dLy}1Zu5tn6u1`FZU50_E z=vTKAeWO*kwes!clg^#6v$82E0RVE%!uw~fd~0Q^>KQ34g^KgIgw97}wMPUVow4=L zK^CidwEpQF909xn6rbb3AY^s~V*q4&`IRt|NySMkt0_jw>9y{)?XUbdqfZeQ?&9UE zx@o)LrjKsc*!v&D-YQKpcC}lZX>BK(H4(h4h}X;;o)`JBxCOS6f(G2EIUeVx>N<7n z7)+LPzh5)cTcqK?D2ZPrin#rr)A&mq<0S6{B?Au7{r*{O7n@^zX1$3H! zi1k}irU#xjLZxJi=HfX39S-3p2|YO-I`Lk9CocA$@|P=V-K3v0wXXGAuDx~BW3GlN z$KB;}N%gvG)5&zZvHFvv>Q=gA$nYq&X(9lK(L`bJc|`e1^#qZRyVwfrV(|^7+;YKo z(A^m$B_)W3l|v@wCnP9jATS|`Vg^)akIcJIivBQ+M-ytU>k93SXO7-R1Fy{?gh=G| z-0pb5?OkS>@vmRAeYaNeU883NFOe+pTyt@;S-#$)`Ks@sql@!tTNDMW%<`SAiZ)J?E3oSd!{5IR@F`5;SKai7A;BZFB&U zux)XY1)E#@I8MbzmK9$u8b%6KfyUr+K*l-A_c^bQA^7`0`iX31iZ&eid!@vOq=P$| zSYUy)fyv0uF(e-ut(txEJfs7L-?=lB(UknBo;m}^IVQPdlU7{Z$?ET-{B(Q1t-Jmv z?=YtAYx(Ja*Kb4X>9zTz#6+QqgD;r4`={=g0I|jh&N_}qr9mdAZF>)r^UH2xK5TMX z$+d&F0~aiWN`wG*j1iA|`G|aG(c22fH7~bu49ce+N6cFT(;RdMJ!;e+6Eun4jlKQ4 zV`(YpA}>9cBd=Wg9D0hmWmDy9RAr}LS7z4D{7XgN{{SKuJ{MfGkDBuG*8O|$bLnug zUP91a$rbIqk?kf>sPeDfVb!q24DRDBbLoie@BBAmt?9l78bpTP>rQK{EBjk$j-6;@ z3yUj@r`pMNv5O%))=h*Gtk|yvkH>II2}`)p;~=cc!Fyy9cH@9g9ZBb|Z7+-^U_6_r zk$5{}kOX2m$>fd?BOGTK6^qO2B`B#%F=@EQE>zTKYeuKK?A&j*ms)6H$B**RZU z)MVuw-NyU7+rFFGv+8^8AHtXRqeIj!EZI<{&Ar)JqPk0n_bgJuENVkK25n-dv$jO^~%L-bpW_>#@qL1RhAe=BZQKtVvP3{%P|z2sY?+k z)zZ_vxvv*=)ReB1ZSyS`bk(h|*C|RWGNzm_@U*R})mxW+?CsmDX8!<)J_zYHvRO^x z`K|8&y@{{1{a#ZVeT`%ub3r6ANbEpx~myIMg+BBMRTU#}O zZV_)KkxZgTGs4>=NYujWq_3FZj)sW5Q7Msk+)ck51g|S@+JA&OJOXgo0~@-6d98?i zLpUHU%#5UGZjH6{WX>z$m zy=+2wcH_xL7EJY$!Lde$eG=xXE><4s+3v9q{ z!L!NhSzaproU{)V+gsV{8s+`0R+AY~?X6)gBQiW?SecI11@{bYIRNzQ=<#@la!>k9 zfUi(hNdRzrbUbILwmBzO4S&pE_5DF5Spg*HB#z(?-A}Jt9y1vi7b=&OQq{p<$-ZRo zvc2@a$!-y$LQSZ~*KIpCm!8cv&idv;s&ZV;C6w*!Ljx zuLBzKHET+|D^8tRJu6;*(JM71rkZhfvQ0|LH%VEZg#}I!RGbu{{EaS0u9rjr%h}JKr~l z^^1mENFunnw!L7bV?JS)F+62NdSUbn=8-)Sd_uR z0de?LULwD57U@@dJ=U?}j}O~wR_4=Elfv4KrG?$?xeNqTUffyT-NYl@#RaU^?en;1 zDsfyiXPn`jY0=ExDiV@Y=chW+ioNAH(Y(KTXDf0zDLZp5TU}F*2CQ7Cgj1-Z+<9DJ z+lqFKsw-YQCCsJEuHAeG!kPw;uXxJO!#Z}SaJKU5SC+bk%rVAhwEG0@W=v>gjtj|W znh64`On^tV{KLCy`Y(?D6L_=0S5QlPaSi5|sRlZ3v1t>k&Y%&t`T{@ECT!$K=T42# zN=O;N@ZZC6;LS?TO%qs_=TFiVKe3lm3fivo`^g_ty@WybxmtF2^OYlZRvVe0EZ<*v zKgN1?xuVPAUx}8s*H$dj$7^(x$`UB~cv+dGY0^cJV_3&xE%0CifZSI*dA|Wjlo5vU!4mr+#@Z@K?0|pD*%ShwX?tDEGT0P@k zU5HSo`==@%=2i;ka_FdxtkI3C2szDtX{r1<(#7nnp!kZ~`qiDhgpex98kWpyE0eW~ zsUWhdWB^W2HL-2*O6FTAu7jZjN>g`oK#h%8@*gwSNW6upHWG|Dcv`FILcO*zpC&?`uVKd0cIZ^ks)#F8-14nooc^!s`wdKQn!VnUF#Lzm3179tfcH^k81)RBPf&}0Rl4H$Sbsm0D?&v;MOeu9+d$oHpntY zRFsn^46OSsk>Id)y5Z*k|>1E|sVHL~9=6#AuLAeT*9D%p)&{V`+C6R=SN?8Ddsq!5(ZB-L#1JWDJVwr=8MrN>h!RymgJ%m$O&Z+R1y` zJKsdw&RJ}=v>SJKTH8yj?d$qqM0~i~XeCh~WpKnemji&Hf=@e?{KIen@BtVHGbNC1 z$jZT2jl2~dzEj6J9X&CUGhY33;1|>`ZnnVMYA9(fp?%j1ks^QNK&JtW$T zdZnbE-OfqjYeRTR>ei8M+q+w>7MdPWHjRR&GD@fQc!Tb^$ni>@~)!8iouHY?m5kZs(samZ}MC<2W7Izdf)pGsrpV z^{Ue8MCFFyTb-lsoF4s1$jLl$j=b~eEvL$HXMC24@`9TuSk6`k&U5A2L!GO$4;2Y9@SCwydBLNuqPXacqEQ^>w%tdGDa~^ z+TA@;`857R1FuuZry{CJr&~^@DPcQE zXD4FfqVOdWo+~rsd9GsGR^f~HrjMhcQla>T2`A4n}?tX0N(+30) zI%HDzi*(wu^Zd2Y95>Y~`CIa_=T}+^fURil<`2FkVgrH?0lN@5>CZ~bZ948YVo=7w zeBh1PAHqfs8=Uix!o5i>!Xqr`#Djzhk}^mnvl7HIu1ElYcsRhO+lx5lZ?!;J0fc2! zzX1Km9ON8~5sV(>n$6=U3$JB5ianE0O>CRB{%IwznQILRHENN9d#3KbeXZp0_nuMq zY19zT%rXcrFw4(EJAu%2`Ej3GXO$)tvte730^|;UT;z;^J#om!4@&h-TGvRrw`Q`k zytlqy6};4YQlt2an7q|z1Ou6NhRzfYoT#>F)CN^>KIteh$G+}5`VP&=#dOids*z38 zoi^J}Gf6eGzq=_##otDsm6OoIt{uWnIYw*wqpE9Vb!BJWYu@J~VGKiz^gLq(`~LvF z?SL>&GDZU$-LRw`%6aL7l1U@4rZa<%MRkv2WWZEacH}NdEuO=sJO2Rs@@f^abtX9g z1zVm7DhcYKaM(N$LFxH*#;RJWCcS?{ou-|dwYL1fuejwzYOKo4`2Z3C0ddqE`g6{D zdV$D|tv7t=!~@SCFyp=lP(6vqJ$rWX=}22^svM{pVZ$ly*Nl!a$UQ1n(_^<%rYyyQ zwPGJUC$@PYBNNXUIH&DneNeMGNdEx! zR3}b5NhHXm0=ZljInO+vy}iKVyXiFdk939r2i`2%DinOjcQ^wX&!^Kghe~-+v^#Ty zpYD)P1xIiPAaZ(S`r53P(sq7p{vYrA$>dJ_%kM{KPMbw%j1MSz;IVRW11JhGqc|DJ#~D92Tw=1{NtPDD zi*`UCGUptSRB?lWjz&56=Cp<-M`wR0t^Q_mqkfOI-{#)Fn*RWmy!mV;m4L&P`GY#B zI0O-%NE~DyIKVx68kbr_p$@;lj1Wrg#GASep;+gs$;iOXdTQzJRhB5#2n6FKE_xge z#PV=S=Nx9K4K`sSgMxFxAH#!#pUiQNbDZM>w}vgqwz;>CP(QN7Y=$)Xw=U({s@YwPHoggs zhs;iLIn#4vs7X9Fu#0Pg-?@T9ND-byk1Iru6BF}8_y|i0qF}n@O2-ueWR0iN3 ztG}-2HO*2q>Nm|bRkvp5-!ilJZEj5y=$*NJ+ga(fdFiXDxLWNf+m=_|Ys{VQ^+`Lc z=+0l`&%j>_{?h&vzwqVtj)`fn=^AzIw}iZJe!kP}5a{eCHwBHszoO*LZe%g11ZSFs|CA8M# zkx|;((dN}2-e{(K$n4%Q;aRih)T=rbY0>49p(&-$Q8=WVa7i}htw%0yTPQ{mQf)b0 z@23S;oT@u}MHenuyQbBfy3)!Ca^CJvQni{%FX!fcF=36TvyxkR;~|4D?_x;2unQPu zFo1KoGWn&C$VM=8*!(K+H;8^C{6g?I!@CC$d*dGv={jAkw+rQ}SY2Gh1>NN98I#Gk zvw@oEDzuVFGPzvllHSHkt4YLxZee7OKw%h=$vUyk(nw!mj4WY5+6id}I%DcD*hj(| zhlsyw?}a*AYBtuA>36r9<;~$&EG;yc7Uo?&6gX(z?c&?_w)t*_m5xc8)uTyHb80G_ zWjRXPMMXDzEnT{$cWsVZQ}(rEPCoRdIL6C&%xW{t{{b z01HXcbngpzkk8}$o9Q1@)%Cv%K?K*IWww$ip@3dVs$1Aux0tb{78BjfuPm`7GX3e` zkA@l#fvi5op~Zb^3rif&6~yg$X1MYrfeT3?R*Xjs2%;#{Xe96tC*19YosGrc*)AiJ zD~0KSKfwn=V}D&8Way0f@p zl~x!)pspJyo;<3VrJ%3O<24rvS;yLQ#me&cUnQ^Zt6xUa(@$O)HO|^mO+R@nd#)`d zW}dG0*YmnO)4~4$5hc+)L_9O$o39V*THceX>H5yUqw4VL5los%mNO*wx|}wW+xd_( zO2*BMf!G+@Mb1anc0L`x@zwCWv$cxKcob?85e$;F4R8viiVIt9d7+k1DOp)S``E@u znm>lL%gZ~v+c<3PHRo1asi3p5xAWty;4SCA&{|Y8*wKly?^1ny8i%$ zMa9mk;(4_#Qu{+TdcT)tZw8+CVpu=3?sThZB9iVIVSy!vIE~bi{hnE*l^#grb@@!v ztYs+F~GY2Kni^!ozDh@!Y^gT99y;|n(>Njg`(aj{x36eKMDJ>}& zCwX8>kC1WlUC$bQEYMp)o805WmY%&k)E zmQ@!tAmuA4#e30Lgku{)a>mwA-m`n|x+%im^kchfF3r6*lXAVe=;aCBD+_ZDjIoZ-P%X+Y~DZo2q%O5Lg7zkCn8q!IA&!*^N-sLTBH322IoGzdy>wHRGqlOt-nY^`) ziP(ZT07k~o7GwAW7MTe_FS&=w>0dVTUl>*)$eO{JSV{s>UZW{Sa@Se z)2yQpBv-e#?Jl=_J0Q%~X)-9XiHQ*dhGL2cW08+#(>y%W%97jN4>AubOObgbiS~=6 zmOnB(a?qWt5DmkY3_#jI&X+QjIpEhbaqUG+| zH;PM{q@`_il6UBGa5kZ+T-;mT+NGI>`r#4bluZrgq;cDMGbs_rSw^EFwB?+tE?^wI+ zYdTPtvQcTa`ChSB-$t6gy}sk~>&73jufPw8eloD}W!0~W{4FM>sGF&6JUOUX=^h_n zGTP$V&|BQwTuW+`wZWJ~1gdT$gsUiAAGv%7@GId*!S4ti6Tm(a(R7^7{5(ZYOB>76D_3bFl$tu2bXBguGL){5_fv0^CVy;;Ri($5qnOC?R96$EQi= zPo$6#ENgRUCN{+tTkS~!`N+Y?_-Ca2M)4PhV!QEM!TIl6sgskZB>mpb5EqBd%H#H8Cu;mdmkkJ(4X*5-vWGi_>FJk?+tjb z{uR7hoEELCNu&6BJzr10ArQQgSS|LK6|SL>cijuQ)^{6T7~gYO2YLSh1jzVb;0;s2 zI*qrAd`qqB9vIhcwT)L-xLa1!_4c+7*3fF+A44qKZIn0W(q)?7{{T|KjUt*bjM69T zM~C$rdka`JD>xvzn@5&7H5*tPA7v8-x$`6ii>B!16D%Q=<**N>3-fLLwWn(Baim3K zcy3`bxM`m5&EsZRZIjIk{&S>HCiQhxR{49^ejkrGj)oqN1{tMwhQq>i)E~1`sZZI? z4l}Ij)U7!3RB92N+D_J%kd%1pigIy^y4^P9 zpOD#J=$D!R-9RG0Y!}l?whyK&+FskdP_4qx099CE0x$UYctkS9=t8o%LIXzF`S-=1 zKDw90Cr{I7T|UV!QcIiDEJk#;O}<JGX!~{ihF56OgL!(xVJGnk^yE40Qf7#pALQ~T51#MH{K5MB)Wyg z!&yMqR#Vljdq}F{q<^ z^C?>P=88$*YU#(89E~R=+@iUalS%BHlXhA)c9Yb#@gw7%yV>fRJ%*hX{gF$X8{?`u z#Ief+mhvRgN9L@eV&Q_b2#i6{mj|E2kJ?}1Ux49%3u?MIhV)Mf>M?7V&};hMg%p;M z>Uuu08qcQO-CHwUM3Y1B1trF8JkblAeu2G0z)Of zVUgBoe5na`0m}olf)(*!pyaCyPMqjatr}CPoF!HjBUL_XdQ__wQc5nHahkkSi%nkE ziQ?j2Xw;2aQ})rPILT9f<93txBJFu8xXL@U(_OB77x1G@)FJUr{k^;hm$tqf@eZ3U z#B9H2XSuVv)3qNvC1i=AxEBafcaM}ZGYl__4RtS!{UVxUy0SE1{6`%IRAyLzX zSkj|K&Yj;h)FsO#++(EVx#4);)4ZGat@HTEDd8t5DNdZHQhcx7_hls9H+sQIsWkp5 zyDKz&r!9rdYh{0O(5k)+5C#FET(A*JLaR!IZ3}Mk#8a6(@*7~qn%!O2VH!mQ*Hc@` zY$V-vVQ{YBzuScZ2^;tRTDv%n^0_!#`WM7r2edYj>XufrCAHeG-jYdYj`0#dI^J_B zXq$fM=eD?5(|Wv-9mXt=I{yHKUVCY^B%TD4dx%w`DszjcDJ3Y%GK*Z%oMq=f*|5hQ+ebbeOgy+*Gb_h&Du}ldakesgf_dx@ z%4kIrtmY71UfdR!cww9k$m{?qf=r8*cEA}SPZiw3rQBbf*xSF_B93yglpbZpyhvt} zVi`$Pg(5dBR|QOCox6dfHG@NLCTBvDv5DP?WQ)ug+F7zdkl?1~z+mIJ#*yL*G3AtH z2RKxURPns%J6k#6)0X!yD3FV4%YXq z-s<%k3eKI%^H6@zy<7C>g-Pp>~O|s%y9doIr zRYA_pst6dTYZ|7hc$RSA-8IRvYq?{&KRn=01nCXI1O|*4z*Zv#f++;BuSz)eR-B>D z8j_6Cl{q%5LNA%dO{XZ?OMfWEJuiPYS$DFl2gxW#P`qj_Y0gQ-G@D9EwQgH~G@HA! zUqhBPImIc+1Bp$dV@xea0#bW9a$0e)JCc>ejW{xbEg&37*VpTycx8-8o6>d4n z=SPS{zhDTSL>C*r-m+k|sj;@6X;=^dbeu(ozzwvQ1Z~K^+UyeO(3^0X)_lP1z!iqh z+E+xv6S*1Pn8r(TIp?Kz)2iI<%VwR^U1OqlT^-sAlx;F{N!cQp_7#2}vl$w`LN=L|9-D?7K@0amfUXXU{$%+uGmXX@kr}ym9i%%roW1 z8wP?Pxf|a;XCx`|@(AiSr_`cZ-r6Wq)v> z)tgk#0DTXUKg(eWYPaDHvm3oi@`_i%v;(>b*T5%=0F+<&tVQ`=3X* zPxuEf_HXpIhTbcelWqv|50n{H5bZHwOpZ9%tAVrcMqP8DLelDJDAyq zRP}I4+k=8Y3>fFuy$o8%Zxy(0LP_Gg8JU*QM|)>1cqD>=Cz1oM9gyWtayhC#An^UA z^_{)!l0h35Yh<~H5hF?u$R+P9oP#3*q-P)lRZ-Bz!O^ctN)t{xtJ_C;Mei4TZD$u0 z?8&F?u##11)M}&}msFmq+Di76ZKqW$?wV#ix?ZuybNhR&Iyc%uW$L27!4z}_RvI#BO z*>e8?Df3V(0#9Od!%mhX3n@q4t%p`r=Nqc2E2~LKyQI3`rI$mxb!cLjv}#l<%JQie zqUkwVUy-Xcn{Bk?=I+j3>rnC`p5||oI4+}!f_7OMLP$4l`CBUO)F>rEV!1fl_L^?~ z&#%JHCDR~pv?O>hb!Rgt$Q7AYo+sE>EHfBz2{=~hFRdE%y}iw;Upz#u<`5Cj%JGoc z*rV>1`Eh^=$uv#jj}X~u@eNMVo+&OPX{NQ27tO)I4A-i_TmGn8HKs_Oy;a2Z1kFbpyQ z8%_uZk&}bP6;gY-(O7J*$FL?{~KL)n3W=>UYL%CjS2bOJDIim?l7~SxS%g z93DvT&VL_Yu4_gztTMZs*9RbHj(POso;@p+hH!s`2F_2giTa5?LYB1+px9%cX@i~;ut2OWkFZq;ThpDg1NVTLjhcs{4* z?fkv#Hm<)fBUJ6PdOoXt`>njrhB-k8srj;d=Yz-x2ZQ+FjBs}W9-3+h!5dg-KPz>xZ!L$#X&`23*d5$qfhU}tFu`HYamP+ZL8+v*y@wzL^CKAA90m*l$leGY zx`x5^;+1zOXC;u4oQ#vez$A3wj-7Bb#wqZ<$tk{A#~}01Q&$&Jcq9bDo`f+) zlLzU}0XZZOT$Hcj&F21z`!M?jg9>ToB_|UCaFPkl1T8}MKzRfM zoP)+Nat~3?PdY{rX}Im=)%|V1;6t32lilrmrTJUW{v7JP30{THVTgl0u+xGNh8=_r@>*`k!7aP9G3jAqy~) z65U?_#<(Yvc-x<+Y@BAfr$)C}-rI87{ujUMbi%9^tt&pQ-CN5`{yukSek1^|Y>-Ad z8$iey9Xf&2j=Xl#j^$E3V;ynVL=9ttI0}ux)ON zcp&uY!Rwr3=t=9vV<=xvs_Ay>yw=S z0FE-I^|D^6etm8EmkNp5-S+bSzIz=)K?M7Rw)T<+19s?Fp(?|wjNtReK)^L*+FGGf zV2CP$FgU`TWcr>!0~Ln`q7*5|IQ}8`m$}ckZaP)bd}P1{M^Z;z92|Oc$83(=_QA%Y zcTJ^jQhk2*bSD;-(rs;Yyxs0>EuDja!8S1jVPt*)>6Hg64_=tT=Cmy_Y{<|}ECd{a zvbYQnbF}TpJu`vZkyz2lTNny{TxWI;dUMcYzBA9aBBp5^FUq6)*(?K)c-qI2#(II% zka?_}ThX^9`@OvE?wLwb<>pN*J6p?54%**bmJNZmD}`lolzAQ0N$;~WA$znyu4+=e4^hU5YX2e%!Uq3MkE@5W^FWe=DX;E;2X$FCX5 z$8vuh)Vw4my5Gqq^0oazVy2r;?_{i>`PlUsyit5vT1hPK0}_5{*&96I0FjZ`yUa^RSdT1s-zcaXTS%b`3X^vT=&K+#Gtw)p#!kvfs>z8z|Xk)^UZF-EyzJA z4zU>u62t`F210ctwmHr=;1QbStA~n7B$M0M%liKSGpdzl{QKWaKP_&1&6d6#D{W*> zN=h9@IV7o2++gR7bM!T{9=KuwqZ3Gg0L;5wjzA-BOJD*?z&rvu;=D%JSc)}4ETu}W zSnS@8cmsgTw3D0>pT@SWwMM`zA{A^EDIrqJjDxhVQ@|jePvrIM-=e?u`1@3Pgp!3(gx$!^0?}8LW2?R3-)Heg>+pJ8UCrZ&)ur-rl27h! zKgjoceMQMrCPah{*(ZUH$J}7x9x_4ntvGdOOlSDB$T`3{`_0G)*OAuK1fw2NiChv6?a71K_v4{Hy#;x-u$-LA zN-Z~a%I>Y|)Lr%3-d8$dSDMyM*(;}O-D!2N>#sw+i&0l6mp?8J51EiTBzj=;fynAP zttf8Oa=5s7n1%bnk-Fqz@Gx5hpGGKB85Ufvr4hjDNBD}ueRov+a0idC&m>?G&KDy-yo~Js z0BFqs0oFtZZZZR84cG$*rhU)l&2v=3CwsyzwW8%p>%FYJ{JNbHt)pqZt$Vj-zHNR# zz#hyUzkFGms-npfOj**h(w#(AiwXNH?V_4OF?|(Gy z<)*7&H@WCzTeOu-b6Q)Um*x!wO~A%E!9C71jC0TvNpCicXO44X5uK0Dy8i85#Wg`qR?>c-!V6fO-b>KXmXhlh}9l?S!yxCm70U zJ?%NA+u`Q7;q$$js;;kTMLTtIPft6mrLS~)KB=I1d&IFZv$xS-P&nHLuNTKI0V-bd;31jZEf`ndx-S;|$1Cf)*9nPEL^|wH*^C}aQhtCITKPhY;m>C|U-npC2uuh!t zxVo;KC3i|`RE(o%9!WVrd0E{yoRdr5c1XYWI`Nch(x=TOXw7LTwQXY6p0>5MOIsw{ zzmr~k7uQTj?DE*&$bkIl{{Ur}t}+8ha3M!yg4>j_JGdvD`G&FJ-ETpV#i{8xcBoXk z%3*2k-Y~!h6T)POV~!cY8Nuscd+6RI(6vTeTZ!$%N~^TYe6~_R;h#HCU~on`uSAbT z(R`&5TgP&*5{Db2o-7O!BPC?vhst*a1xX|WjBiVeF*teqJYF5i>-JqH^?Io*#rimF zrlvB=sMK84YAEfk)Yi{*^?x>gP)THPB#k#I`=vf?=a%{qK;whY1FbP3PzGUf*l~=O zY#j6%JxDzJag+LEs(c#o2Zvpi%3a7p>FQ`4Med0xBwJjth) zNSI&RuI-l=v4(tSD9;&n05BsZT##}wabCS1D8N^0GUuaHOTwzxU47X_xJuh-;`-R* zo>g8B@lmN8?;YD+(@Cp**F)ktETfZ$g@a?|ap}k(GWG`t-yJxr5@{@~K2plr0FJzN z&U4N=B=+^`^}N3X?!r8_^Pr6g^P{*{is5ny8&QTGbAiJa>6PzX{J#pd7}$i4GTlLK z=t%FhG7wKZV~l<|?uK)Oe+_uGcN;lspG(~GYuxAfcc?_nuWsNBl5lc4 zKQO=`j=1&jj+I3C2Kj#awm8b*t^)K`BpjR$4|C2dU+r2~x~&xZb6r1@xgS)YT5Z1X zM!foI_nr|xkcWkiMI`V-@OUE_>N)5!kU7Qysxs*%Nk)Z^4+YeofMW#p#{eAl9<}rf zcrN}U#5?kGzF_DFUzjhyBOIOq80Ck;F5J&-z>H;8az3Eo5ID{-Kso1%rJ7So{_+w@ zU*lcZo%{CJVqOwo$*0QJ^Zx)d=LxiY20lY=6^H=x(?BA(mXzWx6D`k_1=*V%8UM86AI`Ho#6C8g1N$wdSK*oM?7QC z@Y3wN6y zXlQcC4&B@+8DPYA2Mhth9Pl{DTvHQGbygBbys0CSGNAO@bDV`BbKmi=p(OZisz9ZZ zJ;d-&1S!cQws1yy=O2w_&){82Noj2u^(<8nBiB6$?Z>A~=QOiKn`)wIEnU~+sV@lD z@o|4I!smvrjEtCW17|AAdyqif2PYi!&;ol@t*6OujkYG7AyN`77iHYW zy(fe(5VkEOKrlz{$s+_D4l#xU9P%;_I3l7R7t}YBZKPD=0D^Ih@9Lwe$G7BbWtzc8 z@~IWKRpsaRY){oEqfy_>r<>cM<>{vsVCDlVx@FNoP=UtsjnFX}AmFghMtC(L(d}hr z`!MnxjzfY8I45aSla4y$(E3-WK7llUB(Sm;`BP|O4u0-eY1@p99mRRcBajtz5y5m| zPC4?)89ZRH8@is$pI!x2b4qQdr2SLT{yN*w<)JSI^-e8ovs$O?{dPRGXzEFh>LLOA zjgOE6{@5EpC-_)~}GmZa*tz5HZk$pS*H&oMd&*E9s-*gqSMJ z6DJ=bXtR;Dlej4)HaBBA_3OnE_yuO+c;n?GaqH@=i-XTUF&#To{@0`LK7LzwZS?N0 zgzz%$eu?dFuKHhF`u=Cl3!ultJZ~cOZNru5c9Yix5tGh6uxj$@0lr@$-8lhVZX0oo zZfxWX^1$PPlh(eIZ-w^^N0wX$Q@TMG5d-ttXw~-R)C-)!mBD5HC#N+nzlVq!SlI0t-w{<} z!*KzmLQ`%r)rluL9V_V5;8{TpEDpHf{GY-H7(4@>IP2?Ai@|pJ2&r)n(!`%4Mp9S+ za6%{m3}EEvr($V5@`o;yy_KK6&26;R-{tv-_I*V5x=!mwZFc>7eaFrJ0N55+GD8*R zg{9oP@@AgiF>r`*3JINe9AgXfAD0;EUN7B_pD#hj2wB7tqITiHpcUxh*?hU!q^k&S+YTKEDLWdT`{n=bEc`2dsmbB(y? zsX6P%0;_m~;W}&jFNi!p9IFrfBpM#EqKklz-b}i#pK)Ov&V&F`7Pu2I-JPk%P65gB z1qAG-(%#efY`4+g)>^A_x23ul{hc=(a_en5U7g#y_mfL~b-Da?>AEG1l3T-RW<=`l zlRAFx5Z2A*o*!v3yQ@4PgSfLEg1=b*0N|K^4Xqc&zY;z#Ynpzf=SNt)A>oU-B591* zw-(XKt}ro{mPulI2@%a{EDRfK0_Bu_#$){-e#Bo5JQr#EHT*8U@O|~pp<%9RQtLX+&CR5- zN&f%|Rn_&^{3LLfF(H;K4Om`j*6uQ|1*~k6Iu#_$vkGybCi#-(T3ug~Qf>8Ci)z<8$h2z<^|F0ACxlzG3$phZ zc#Xu1iJmE3OlBnE%!nDCh6y;YLON}}?H1M>d)Z*Hy^k<~AVX($x9wA0ApSLInWNeo zL*@gF43AZV!ZEC2TGHK#+^*hBxsg|<;(-WNY%tDtkTOZGhTFn&2#A5)h1kmH{bG;~ z(7z`E333qi7|Um;&*C#mQsuPTQE!zwb!n@)D5l(bnu5A%JuPN?@WRgWe6hTeZ$`9D zJ6q+hx};%TXdWKAy_V<0zuFMR8xOL=5u%lv)>cp@b}BZ{<@vI-%n zA6L_+)HHC`_tFUFmRRGATR^cnONoX=k7kXvfK_16<+B0-YVEX-4zvlrcrIm{NLUHu zjbIWpq3XriN6(VX6|v9CO>`C-8M2XOxPohIsgrKgGRbUJTzPA}1}eLLZJP&8rLak_ z0=6~@RHyAFQ`~Tjr6nqtaguhN99^$xDM>eUlS=IGg%^0sl`W*wR*Tsyt34OVoTbI1 z!J^-4`e2slO}4zAYq`}txh`1A3=xWR67h3~e(bIwV*r_NgGGr&TD=@ z3@o?N%On>1l1mTT7c}uYFRw(QS0D?{?eKu1mrilk46yu)Vy2WzzJ$N1DwP~| zP?iH>sEvAgd7I-6`X)X+#WN4Vk=?M`lap_q%P~7S|wavbl zb0w|1{^rz3g@>IQGd;s@B(x@VNQnvyMJqCbzyr%1TqRagoeFcc3BoX&ZWP{%HDe!z z&MN$oYmzdTGfkvv%HtIn&8<|V)wQ?97TxTxzKyu87N!=B;c)kH>ROe&lYN=wodvF7 zNp2?)tdZO@Y%=CMYhxo!Idt9pT=!>4z0?|8nOxh+o$*Zgn>72%QO9j?e27n#CCkR;mP>?F=Pu%?5nOD4;vqmCt4SY8*0gt(E~1vs#_>sL*ZK z*;`l8=d7obQqr$&b^A%6Hg^y*-`ZS+mUpq4CKs0STS(6gGdxNJUn8^)Byu2DV09q0 zzm+cUtgi>}j51p_%ZX!jRUx8CVlp~8;ho9}31OV^PO!Mr{8wvr4xVlj+S2Gja>5f5 z%`^p=#SD@d#PNnrqC~Nb z#!B){MXM{NX04`G|LOsNR$>O_r@yGT`R z;5N@!kHq#meyMdV{vTiL`&-7ixJc%L>N}+q3vH(2+HW@8I7cQQyodK~&~B9KLMf@Z zb4fQQ+*XcFDK@mbTG__;O4idELC2R~Sglo*T-2}e@}~55YnMmXSJL~II(EIIN~clR z#N31Cc+!aP`kHC zK4J!OfOh~hT$Q~39nvSb(QIBlK27pS$oG*Fw=)F|<%y;9No7?(FiGj{XMEt7^7dJ?DwM2WfWF>7Fptt;O~2rkc{17QQ6X?R?woGh$0Xbr~(b z!88%A%=dfVQa&2+7lE~382Iy5@II5_T}xWmF4baPD&E)2T{%)jGhS;mU3oUzHKm+; zrx%)>wy0!{E#P;#o*3Wy(eVYfoz9kRqPv27iGm@9Wl7??lL|bU^0LOTGvrGlieMCy z5%FFJH^ZyzPZP-(hjf1pXlvs1lK01cA+yq!JNwnP208I^3S><@@tb5%D0P-Z#CuQZ zIcFJFOPd)^H8D}A7%WHD9V`1JoM&3fQ*w-X{{V$F=QSA9bljU>Mk6VW{{VE{X*o9O z`#b!1O+|bvE?cQ4xm&+Ak^JU=!!h`?#h()5_(`DJX|UYcLw4RT*O~36(DZ#a*{!6D zR=T;fGbEGB*LN1WbVGF4^I2Vp)>K#ix=4LbxHS6scQ|lGTl7Vz01SqnA9+dWmHf{zWhSQK55}8%NJ^Lq^VYmrw0}L z+V$}*e02St>C>W|R1;F1olaEv7D0zeDydUfjJc`Fxkh(Url~i1MW&N-Ul+X|R~FIy zkZXSiHEjdp2C1ethvK_7wu4dAUqx>WYS)^cl=_TMrdV9wTES&C&6Taa&D?NFbv$uf zNM!^_%+Z7M&cERA5O`|-e-3zuMwZg!?ag5{Q;6h7^3f%ZS<`#HperO#`}K=!GJ-)E zAJ(sp{{Uyt4tym~7ko$5wOF+e5#QPBkn5f;yNP0Wbc_4AE~C-xEF_k6kz=`r*}Um4 znpKVyv<5jJ7}>arYg=@Q z?rhrL;%N-9B0O2i_b?nufW<;smg`HBG%(YxPufZ~Dme1{u$*Ibs#I`mom8t%UeUr1 z2~QgMOhq|+B&n#mPONFZM4-8@^^Nz86r*^!!clR&xt}ld#jn^juv$+&oZ+1o!tN=Z z5u?4cl-WeUvw|bLvw{n|dDk$=CRa%g;A?=s(`05@4ZEwvikDIV8QW*xNp_MB;sWks za83av*Yum=&-f=F?ANXQJOcj!UGc^J{-LB@eTT)jnuWHX1+J*kJVRU3baQ1qu|;h# z7Z9z@77M$t9eg_RMuDeWyh;71J(M?gQi+tvlQg%aOF?{us3WCnu+7pUGn~{#<26IdV?C<2$tZ6|K)0${IzvrlokU>sNKlPXv?O z%G>hB;Liz60*c_k6l3^hhG`>y=&VZsGlncr11AMG$K|wq<^jf3TYagIhv>4s1V0M(%kdHX)-*^7W(o0T&N@Ty4ppX6XvV1bOD zMSA&mJ~O=MbtuMZr|(M9mhC9rH+d^Z^Uu2{nGA6^F*zk zuI_L!+49a07~;a)t(5nXMnfg+X4%n+87mlxK1>n5Hc^3)2?LNhst_PXD9YrclEJt~ zB;}WQz!@M0BRrmcC^XVuNi^)<>PhrGDzv#`?-@#81e4K5YhU|% z>GpP#en`_-HZV21M#zCm&j6XxQr=}4M%vtsz_Htqa-*Q*pU}KFcdly%Nl4+*gUs>} z!Y`T2z^Hce%#52|L1GWD1E!YBSfYaaa=xFa?v4wk-cfELAW3RffMC%ERxC!=Sr=nA z4muwTTgWeN9u-e5p+%LlL56cFi5Y-6k`oG}##>$0}jQNl_|x!rO_Nyk+$X5yNDmTFg8TU+mJjZ?$64``7{@(E#-6KNZnK1T!+ z0+PdT-UI;09N-cw%=IlE?$+kr)d7hvLM6n@+|G}0KmsR z6l+TMcAA!+_S);&chc``7*?dL-mz(EYu(#x+kU@)S9Ew??2QEXkk1pzJOWt~J;9SI z%*G=l5|Tu*VPS2}BPyu?o~+(7Gcqh1i^y4nmSTkf#N6RinB|iZu4|Ni58QJ^*hhM&VLc zK&KH8oHhyEiU`5T(n_64B<|%66|Z%E%|80|+p(NuI7dX3T8nmZZs}<3?3cRi{U2ha zz98_&nI?1#f_J`1vAY1B$B;asfO`xK4lpRGTKh~!WoB%tDsVW+I6b{Z6|Xm)Py8D{ z{zS*w&%HnVCjS6}dlWs!WMCe4k3ifW)1~P@EU_uuoR$aY9ANRrIqoy>R)*HWAzbYP zC!B%MXWP@YM4ov(p;|oy}f-c_ZFg< z03Qm!LPp?5K1BdLP!Fvpc_@CGrD_L~?VrD`b*p~|TYp~GYn#BfN*ZaVuPUU>K= zP){754}WZN&PIP`leI_#*Yq`yESK58m-(CXMWngx-p~3@=8e9gDviXJ zC#tgoKLB%|$DkzltrWU0cNHs+y+ZMh!yWs6b(*Pe=%N`TX31|bHr8c0z{7w*UT`~g z$2qCcI;g-W9f1UJbL-B1y7QWeMlER@H+}BDZtJh)G}_YlR=%$8{geLyfOK}(425J& z5zoXV(i8EJK4XFo2OWCx$j9f?HO<2z1BA{!2vN>^9y9Jc0y~Plmy%#+ z7dSgX&ftAX=L6Hw;8!fEwBFx;_5T0>-A!30o}E+vnYZ?b?Xz&`#Cq|-1P;F3A4;8L zON^z&P)rCsIsm}%awHgVI`NV-*R^KE`>;qohFgQ4{WI&|^a8D0|S^8CxXlJ30!020b+wsXYLlO#b@kr;MTSh3F81_%IS12`Oe)dkay zftSdZSv=virNo8AWRsRwZ<}!HGT7&)4QWRsDEVY8c*r~z!S^3b9+)PsB-z?uo)1yq zzE3?l{*={Pk-Fw>e=N0Heax3mo42@=SJgJR^nJGM^)gn%@uFWYP{$-N01`3C!2lc% zbDZ`3>Bk-Ha~LkP@g=)AHwHyz`G+P*_T&O`qm}9PuC50_*fET9cLgJc#&CG_scD4w?Kj+$z z*rcN+753zu5ywu02e)ry$4q4XoZa2i@815l{O{+`)q6-gB%0IuR=(bcPYuel2^Eo) zslx^sJe4HpJqYXUI2p}cg`{K82LO?~s2-gLG4=kn#x1(T#AK#P01{OJ2Y^=}$YZ{0 z#jMvbKbX=y!*SZaV;mtE#>0_}91lV1SvoP+&1tptf0;_N+3l^})3=_sXJ;SY;JyxX z&U4f8@7Uwm^cKJ-~kwHF93iyV3CqI#(x^U7Nc{3tqX-UtoqSI1#dhV?Iuj!hC`*FtBPoO(}un!!6haGE5+WRb^zW{#XN`L?!BTPw)m5CQFz>T9Xf^@2W0nm14fZTUQW!<^)I z=cqX2ubx|~I4bEI?l>E;q;%vl04_a_exo?lj@@J1wBVy0eEWdO$s4k8xbAxMTyvzP znzp?fOa2GVc7JzNDstK1eeHk8L)Kutv}F&zJ>cblB(J{=Ndun50l@m`!>B_e0v<4O zHU+}~!y_D)z~i2Jk;tzlh)6b=rerJkfO6Z0H)Cn*k}<$It&3K8+BPi@@n>t4W;_s1 zFf)>RlbjmksfTuZY17xs^yqX(zS=8wZ?B%)c0FbtMdJ)}3vrS*qXEV^`E%{pu6=P^ zmL4H%e1(NwN|1OhwFWm5H(+3Mo;!11X=?JkYDyBI5rvUllae?)i8;VHIO7Kdnv)Jj zHeE&t`^Zlu592C&WDdQ0VCJ~zg{M;LNn5k&>D`?%tm2bTUdwaW?fgM*6Z+DPN&85!zGJm-^-cYYOIqlP$^JqLlb1@s05CgPq{n;S@ z0C`3ZGuMyLrE9^fm2J$gk(?OWh|fki2R|su$9!Ynu$CDm?^-g~Ogz!51^=k!AP)_!#eR*7DrxklzEkVXg>rQ5*_kEME zG~MjeU8J4;ZtkqQEB4Uz2lEk77DWdNxP8T&uU*8J01|o6e`7VI-eR|tB3uaAq=h6e zwY#Y*aIMGP$F6% zwza&l5=@%8*wZYj2#P4#at>2;8Fs<${dmtooT^~yd(n+qD{ak5!QT3(7`lmB-E${q zws%EFyw#hE^W~Q{lG&^Bwwme7ew`0QisQ>=B)7|qfJYeTxXwm>PjQUbZ=(3OQqrYX zvc9{Fs01mM-ZshO_i~p*f$F4tb;ps#tKX7_KPq=`mCTRi?!n~lo6Exv$2{O>v|9S; zxISTvBjwuBzszvB46JYnBoqYTcEGPA6PGHU?9?T?*Hyn&XD*k%j@?y`>R6_}7UQ+; ze_sCpr};0gyfg7W+U_N^*W(#y0dG(U4D0$CZ9ldz3LGb6rE1fY-wc1!o z56VxInB*j=5�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 - - - - - 基本操作 - - - -

-

- -

-
- - -
-

-
- -

-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
- -
-

-
- - - - - - - - - - - - - - -
序号药品类型药名价格库存操作
-
- - - - - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Basic-information/Basic-information.html b/src/Qianduan/src/Basic-information/Basic-information.html deleted file mode 100644 index b296a67..0000000 --- a/src/Qianduan/src/Basic-information/Basic-information.html +++ /dev/null @@ -1,1299 +0,0 @@ - - - - - - 药品基本信息 - - - - - - - - - -

- - - - - - - - - - -

- - - -

-
- - -
-

- - - - - - - - - - - -

- - - - - - - - - - - -

- - - - - - - -

- - - - - - - - - - - - -

- - - - - - - - - - -
序号类型药名价格库存
- - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Cardiovascular-system-drugs/Cardiovascular-system-drugs.html b/src/Qianduan/src/Cardiovascular-system-drugs/Cardiovascular-system-drugs.html deleted file mode 100644 index 10a5657..0000000 --- a/src/Qianduan/src/Cardiovascular-system-drugs/Cardiovascular-system-drugs.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - 心血管系统药 - - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Dermatological-medication/Dermatological-medication.html b/src/Qianduan/src/Dermatological-medication/Dermatological-medication.html deleted file mode 100644 index bc359d9..0000000 --- a/src/Qianduan/src/Dermatological-medication/Dermatological-medication.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - - 皮肤科用药 - - - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Digestive-system-drugs/Digestive-system-drugs.html b/src/Qianduan/src/Digestive-system-drugs/Digestive-system-drugs.html deleted file mode 100644 index 93ec496..0000000 --- a/src/Qianduan/src/Digestive-system-drugs/Digestive-system-drugs.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - 消化系统药 - - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Export-information/Export-information.css b/src/Qianduan/src/Export-information/Export-information.css deleted file mode 100644 index 516042f..0000000 --- a/src/Qianduan/src/Export-information/Export-information.css +++ /dev/null @@ -1,159 +0,0 @@ - .button2 { - display: inline-block; - transition: all 0.2s ease-in; - position: relative; - overflow: hidden; - z-index: 1; - color: #090909; - padding: 0.7em 1.7em; - cursor: pointer; - font-size: 18px; - border-radius: 0.5em; - background: #e8e8e8; - border: 1px solid #e8e8e8; - box-shadow: 6px 6px 12px #c5c5c5, -6px -6px 12px #ffffff; - } - - .button2:active { - color: #666; - box-shadow: inset 4px 4px 12px #c5c5c5, inset -4px -4px 12px #ffffff; - } - - .button2:before { - content: ""; - position: absolute; - left: 50%; - transform: translateX(-50%) scaleY(1) scaleX(1.25); - top: 100%; - width: 140%; - height: 180%; - background-color: rgba(0, 0, 0, 0.05); - border-radius: 50%; - display: block; - transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); - z-index: -1; - } - - .button2:after { - content: ""; - position: absolute; - left: 55%; - transform: translateX(-50%) scaleY(1) scaleX(1.45); - top: 180%; - width: 160%; - height: 190%; - background-color: #009087; - border-radius: 50%; - display: block; - transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); - z-index: -1; - } - - .button2:hover { - color: #ffffff; - border: 1px solid #009087; - } - - .button2:hover:before { - top: -35%; - background-color: #009087; - transform: translateX(-50%) scaleY(1.3) scaleX(0.8); - } - - .button2:hover:after { - top: -45%; - background-color: #009087; - transform: translateX(-50%) scaleY(1.3) scaleX(0.8); - } - - .cookie-card { - max-width: 800px; - max-height: 400px; - padding: 1rem; - background-color: #eceaea; - border-radius: 10px; - box-shadow: 20px 20px 30px rgba(0, 0, 0, .05); - } - - .title { - font-weight: 600; - color: rgb(31 41 55); - } - - .description { - margin-top: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - color: rgb(75 85 99); - } - - .description1 { - margin-top: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - color: rgb(31 41 55); - } - - .description a { - --tw-text-opacity: 1; - color: rgb(59 130 246); - } - - .description a:hover { - -webkit-text-decoration-line: underline; - text-decoration-line: underline; - } - - .actions { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 1rem; - -moz-column-gap: 1rem; - column-gap: 1rem; - flex-shrink: 0; - } - - .pref { - font-size: 0.75rem; - line-height: 1rem; - color: rgb(31 41 55 ); - -webkit-text-decoration-line: underline; - text-decoration-line: underline; - transition: all .3s cubic-bezier(0.4, 0, 0.2, 1); - border: none; - background-color: transparent; - } - - .pref:hover { - color: rgb(156 163 175); - } - - .pref:focus { - outline: 2px solid transparent; - outline-offset: 2px; - } - - .accept { - font-size: 0.75rem; - line-height: 1rem; - background-color: rgb(17 24 39); - font-weight: 500; - border-radius: 0.5rem; - color: #fff; - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.625rem; - padding-bottom: 0.625rem; - border: none; - transition: all .15s cubic-bezier(0.4, 0, 0.2, 1); - } - - .accept:hover { - background-color: rgb(55 65 81); - } - - .accept:focus { - outline: 2px solid transparent; - outline-offset: 2px; - } diff --git a/src/Qianduan/src/Export-information/Export-information.html b/src/Qianduan/src/Export-information/Export-information.html deleted file mode 100644 index 84ffe63..0000000 --- a/src/Qianduan/src/Export-information/Export-information.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - 导出药品信息 - - - - - -

- -

- - - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Home-page/Home-page.html b/src/Qianduan/src/Home-page/Home-page.html deleted file mode 100644 index d5cb309..0000000 --- a/src/Qianduan/src/Home-page/Home-page.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - 首页 - - - -
-
-
-
欢迎使用药品管理系统
-
在本系统你可以完成基本的药品管理。
-
下面将会介绍本药品管理系统的使用方法。
-
-

- -
- -
-
-
- - 药品基本操作 -

- 你可以对药品基本信息进行基本的增加、修改、删除、查找操作。 -

-

- 对药品信息进行增加、删除、修改药品库存时会自动生成进/出库记录,可在进/出库药品统计中查看。 -

-
-
-
- 药品基本操作 -
-
- - -
-
-
- - 药品分类信息 -

- 在这里一共设置了 6 种药品分类:骨科用药,眼科用药,皮肤科用药,呼吸系统药,消化系统药,心血管系统药。 -

-

- 可以在这里查看药品的详细信息:药名,药品公司,药品公司联系电话,价格,库存,进价。 -

-
-
-
- 药品分类信息 -
-
- -
-
-
- - 药品统计 -

- 这里根据药品分类信息生成药品数量统计。显示各个分类中各个药品的数量并以饼图的方式展示,并对数量(库存)小于5的药品加入到“库存告急”、对数量(库存)大于15的药品加入到“库存积压预警”。同时显示出各个分类药品中库存最多/最少的药品。 -

-

- 这里根据进库药品统计和出库药品统计的记录生成药品支出统计和药品收入统计。初始显示进/出库记录中每一天的支出/收入。可以选择年/月查看对应年份月份的每天的支出/收入,也可以选择药品查看对应药品的每天的支出/收入统计。 -

-
-
-
- 药品统计 -
-
- -
- -

- -
- -
-
-
- - 进库药品统计 -

- 这里存放着由药品基本操作生成的进库药品记录。 -

-

- 进库药品记录包含着以下信息: -

-

- 药名、药品公司、药品公司联系电话、数量(进库数量)、价格(出售价格)、进价、时间(进库时间) -

-
-
-
- 进库药品统计 -
-
- - -
-
-
- - 出库药品统计 -

- 这里存放着由药品基本操作生成的出库药品记录。 -

-

- 出库药品记录包含着以下信息: -

-

- 药名、药品公司、药品公司联系电话、数量(出库数量)、价格(出售价格)、进价、时间(出库时间) -

-
-
-
- 出库药品统计 -
-
- -
-
-
- - 导入药品信息 -

- 这个可以帮助你将药品信息快速地存入到系统数据库中。 -

-

- 请注意导入数据的格式,具体的请见“导入药品信息”功能模块。可以直接使用导出的药品数据进行导入。 -

-
-
-
- 导入药品信息 -
-
- -
-
-
- - 导出药品信息 -

- 这个可以帮助你将药品信息从系统数据库中导出。 -

-

- 导出的药品数据可以直接导入系统数据库。但要注意数据文件名称不能更改。 -

-
-
-
- 导出药品信息 -
-
- -
- - - - \ No newline at end of file diff --git a/src/Qianduan/src/Import-information/Import-information.css b/src/Qianduan/src/Import-information/Import-information.css deleted file mode 100644 index fbb2f9e..0000000 --- a/src/Qianduan/src/Import-information/Import-information.css +++ /dev/null @@ -1,189 +0,0 @@ - .button2 { - display: inline-block; - transition: all 0.2s ease-in; - position: relative; - overflow: hidden; - z-index: 1; - color: #090909; - padding: 0.7em 1.7em; - cursor: pointer; - font-size: 18px; - border-radius: 0.5em; - background: #e8e8e8; - border: 1px solid #e8e8e8; - box-shadow: 6px 6px 12px #c5c5c5, -6px -6px 12px #ffffff; - } - - .button2:active { - color: #666; - box-shadow: inset 4px 4px 12px #c5c5c5, inset -4px -4px 12px #ffffff; - } - - .button2:before { - content: ""; - position: absolute; - left: 50%; - transform: translateX(-50%) scaleY(1) scaleX(1.25); - top: 100%; - width: 140%; - height: 180%; - background-color: rgba(0, 0, 0, 0.05); - border-radius: 50%; - display: block; - transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); - z-index: -1; - } - - .button2:after { - content: ""; - position: absolute; - left: 55%; - transform: translateX(-50%) scaleY(1) scaleX(1.45); - top: 180%; - width: 160%; - height: 190%; - background-color: #009087; - border-radius: 50%; - display: block; - transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); - z-index: -1; - } - - .button2:hover { - color: #ffffff; - border: 1px solid #009087; - } - - .button2:hover:before { - top: -35%; - background-color: #009087; - transform: translateX(-50%) scaleY(1.3) scaleX(0.8); - } - - .button2:hover:after { - top: -45%; - background-color: #009087; - transform: translateX(-50%) scaleY(1.3) scaleX(0.8); - } - .cookie-card { - max-width: 800px; - max-height: 400px; - padding: 1rem; - background-color: #eceaea; - border-radius: 10px; - box-shadow: 20px 20px 30px rgba(0, 0, 0, .05); - } - - .title { - font-weight: 600; - color: rgb(31 41 55); - } - - .description { - margin-top: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - color: rgb(75 85 99); - } - - .description a { - --tw-text-opacity: 1; - color: rgb(59 130 246); - } - - .description a:hover { - -webkit-text-decoration-line: underline; - text-decoration-line: underline; - } - - .actions { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 1rem; - -moz-column-gap: 1rem; - column-gap: 1rem; - flex-shrink: 0; - } - - .pref { - font-size: 0.75rem; - line-height: 1rem; - color: rgb(31 41 55 ); - -webkit-text-decoration-line: underline; - text-decoration-line: underline; - transition: all .3s cubic-bezier(0.4, 0, 0.2, 1); - border: none; - background-color: transparent; - } - - .pref:hover { - color: rgb(156 163 175); - } - - .pref:focus { - outline: 2px solid transparent; - outline-offset: 2px; - } - - .accept { - font-size: 0.75rem; - line-height: 1rem; - background-color: rgb(17 24 39); - font-weight: 500; - border-radius: 0.5rem; - color: #fff; - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.625rem; - padding-bottom: 0.625rem; - border: none; - transition: all .15s cubic-bezier(0.4, 0, 0.2, 1); - } - - .accept:hover { - background-color: rgb(55 65 81); - } - - .accept:focus { - outline: 2px solid transparent; - outline-offset: 2px; - } - - - #story { - /* 设置边框样式 */ - border: 1px solid #ccc; - - /* 圆角边框 */ - border-radius: 5px; - - /* 填充(内边距) */ - padding: 10px; - - /* 设置字体样式 */ - font-family: Arial, sans-serif; - font-size: 16px; - color: #333; - - /* 设置背景色 */ - background-color: #fff; - - /* 调整元素宽度和高度(如果需要) */ - width: 700px; /* 设置为父元素宽度的100% */ - resize: vertical; /* 允许用户垂直调整大小 */ - - /* 过渡效果(可选) */ - transition: border-color 0.3s ease; - - /* 聚焦时改变边框颜色(可选) */ - outline: none; - box-shadow: 0 0 0 0 #333; - transition: box-shadow 0.3s ease; - } - - #story:focus { - /* 聚焦时边框效果 */ - border-color: #333; - box-shadow: 0 0 0 2px #333; - } \ No newline at end of file diff --git a/src/Qianduan/src/Import-information/Import-information.html b/src/Qianduan/src/Import-information/Import-information.html deleted file mode 100644 index 64e4161..0000000 --- a/src/Qianduan/src/Import-information/Import-information.html +++ /dev/null @@ -1,606 +0,0 @@ - - - - - 导入药品信息 - - - - - - - -

- -

- - - - - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Income-statistics/Income-statistics.css b/src/Qianduan/src/Income-statistics/Income-statistics.css deleted file mode 100644 index 0ac7fff..0000000 --- a/src/Qianduan/src/Income-statistics/Income-statistics.css +++ /dev/null @@ -1,204 +0,0 @@ -body{ - /* background-image: url(../图片/海琴烟.jpg); - background-size: cover; - background-repeat: no-repeat; - background-position: center; - background-attachment: fixed; */ - height: 100%; - width: 100%; - margin: 0; - padding: 0; -} - -table { - border-collapse: collapse; /* 合并边框 */ - width: 90%; /* 表格宽度 */ - margin: auto; /* 居中显示 */ -} -th, td { - border: 1px solid #dddddd; /* 单元格边框 */ - text-align: center; /* 文本居中 */ - padding: 8px; /* 内边距 */ -} -th { - background-color: #6f9775; /* 表头背景色 */ -} - -tr:nth-child(even) { - background-color: #887070; /* 斑马线条纹效果 */ -} - -tr:nth-child(odd) { - background-color: #5c61a8; -} - -.a{ - background-color: #4126a5; /* 设置按钮的背景颜色 */ - color: white; /* 设置文本颜色 */ - padding: 10px 20px; /* 设置内边距 */ - border: none; /* 移除边框 */ - border-radius: 5px; /* 设置边框圆角 */ - cursor: pointer; /* 设置鼠标光标为指针形状 */ - font-size: 16px; /* 设置字体大小 */ -} -.button2 { -display: inline-block; -transition: all 0.2s ease-in; -position: relative; -overflow: hidden; -z-index: 1; -color: #090909; -padding: 0.7em 1.7em; -cursor: pointer; -font-size: 18px; -border-radius: 0.5em; -background: #e8e8e8; -border: 1px solid #e8e8e8; -box-shadow: 6px 6px 12px #c5c5c5, -6px -6px 12px #ffffff; -} - -.button2:active { -color: #666; -box-shadow: inset 4px 4px 12px #c5c5c5, inset -4px -4px 12px #ffffff; -} - -.button2:before { -content: ""; -position: absolute; -left: 50%; -transform: translateX(-50%) scaleY(1) scaleX(1.25); -top: 100%; -width: 140%; -height: 180%; -background-color: rgba(0, 0, 0, 0.05); -border-radius: 50%; -display: block; -transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); -z-index: -1; -} - -.button2:after { -content: ""; -position: absolute; -left: 55%; -transform: translateX(-50%) scaleY(1) scaleX(1.45); -top: 180%; -width: 160%; -height: 190%; -background-color: #009087; -border-radius: 50%; -display: block; -transition: all 0.5s 0.1s cubic-bezier(0.55, 0, 0.1, 1); -z-index: -1; -} - -.button2:hover { -color: #ffffff; -border: 1px solid #009087; -} - -.button2:hover:before { -top: -35%; -background-color: #009087; -transform: translateX(-50%) scaleY(1.3) scaleX(0.8); -} - -.button2:hover:after { -top: -45%; -background-color: #009087; -transform: translateX(-50%) scaleY(1.3) scaleX(0.8); -} - -.cookie-card { -max-width: 200px; -max-height: 400px; -padding: 1rem; -background-color: #eceaea; -border-radius: 10px; -box-shadow: 20px 20px 30px rgba(0, 0, 0, .05); -} - -.title { -font-weight: 600; -font-size: 30px; -font-family: 'Arial', sans-serif; -color: rgb(31 41 55); -} - -.description { -margin-top: 1rem; -font-size: 0.875rem; -line-height: 1.25rem; -color: rgb(75 85 99); -} - -.description1 { -margin-top: 1rem; -font-size: 0.875rem; -line-height: 1.25rem; -color: rgb(31 41 55); -} - -.description a { ---tw-text-opacity: 1; -color: rgb(59 130 246); -} - -.description a:hover { --webkit-text-decoration-line: underline; -text-decoration-line: underline; -} - -.actions { -display: flex; -align-items: center; -justify-content: space-between; -margin-top: 1rem; --moz-column-gap: 1rem; -column-gap: 1rem; -flex-shrink: 0; -} - -.pref { -font-size: 0.75rem; -line-height: 1rem; -color: rgb(31 41 55 ); --webkit-text-decoration-line: underline; -text-decoration-line: underline; -transition: all .3s cubic-bezier(0.4, 0, 0.2, 1); -border: none; -background-color: transparent; -} - -.pref:hover { -color: rgb(156 163 175); -} - -.pref:focus { -outline: 2px solid transparent; -outline-offset: 2px; -} - -.accept { -font-size: 0.75rem; -line-height: 1rem; -background-color: rgb(17 24 39); -font-weight: 500; -border-radius: 0.5rem; -color: #fff; -padding-left: 1rem; -padding-right: 1rem; -padding-top: 0.625rem; -padding-bottom: 0.625rem; -border: none; -transition: all .15s cubic-bezier(0.4, 0, 0.2, 1); -} - -.accept:hover { -background-color: rgb(55 65 81); -} - -.accept:focus { -outline: 2px solid transparent; -outline-offset: 2px; -} \ No newline at end of file diff --git a/src/Qianduan/src/Income-statistics/Income-statistics.html b/src/Qianduan/src/Income-statistics/Income-statistics.html deleted file mode 100644 index 454cc84..0000000 --- a/src/Qianduan/src/Income-statistics/Income-statistics.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - 进库药品统计 - - - - - -

- -

- - - - - - - - - - - - -
药名药品公司药品公司联系电话数量价格进价时间
- - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Information-statistics/Information-statistics.html b/src/Qianduan/src/Information-statistics/Information-statistics.html deleted file mode 100644 index ec40e5f..0000000 --- a/src/Qianduan/src/Information-statistics/Information-statistics.html +++ /dev/null @@ -1,1465 +0,0 @@ - - - - 药品统计 - - - - -
- -
- - - - - - - - -

- -
- -
- - - -

- -
- -
- - - - - - - - diff --git a/src/Qianduan/src/Information-statistics/echarts.js b/src/Qianduan/src/Information-statistics/echarts.js deleted file mode 100644 index f92df93..0000000 --- a/src/Qianduan/src/Information-statistics/echarts.js +++ /dev/null @@ -1,57027 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.echarts = {})); -})(this, function (exports) { - 'use strict'; - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - - /* global Reflect, Promise */ - - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || { - __proto__: [] - } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; - }; - - return extendStatics(d, b); - }; - - function __extends(d, b) { - if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - - function __() { - this.constructor = d; - } - - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - - var Browser = function () { - function Browser() { - this.firefox = false; - this.ie = false; - this.edge = false; - this.newEdge = false; - this.weChat = false; - } - - return Browser; - }(); - - var Env = function () { - function Env() { - this.browser = new Browser(); - this.node = false; - this.wxa = false; - this.worker = false; - this.svgSupported = false; - this.touchEventsSupported = false; - this.pointerEventsSupported = false; - this.domSupported = false; - this.transformSupported = false; - this.transform3dSupported = false; - this.hasGlobalWindow = typeof window !== 'undefined'; - } - - return Env; - }(); - - var env = new Env(); - - if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') { - env.wxa = true; - env.touchEventsSupported = true; - } else if (typeof document === 'undefined' && typeof self !== 'undefined') { - env.worker = true; - } else if (typeof navigator === 'undefined' || navigator.userAgent.indexOf('Node.js') === 0) { - env.node = true; - env.svgSupported = true; - } else { - detect(navigator.userAgent, env); - } - - function detect(ua, env) { - var browser = env.browser; - var firefox = ua.match(/Firefox\/([\d.]+)/); - var ie = ua.match(/MSIE\s([\d.]+)/) || ua.match(/Trident\/.+?rv:(([\d.]+))/); - var edge = ua.match(/Edge?\/([\d.]+)/); - var weChat = /micromessenger/i.test(ua); - - if (firefox) { - browser.firefox = true; - browser.version = firefox[1]; - } - - if (ie) { - browser.ie = true; - browser.version = ie[1]; - } - - if (edge) { - browser.edge = true; - browser.version = edge[1]; - browser.newEdge = +edge[1].split('.')[0] > 18; - } - - if (weChat) { - browser.weChat = true; - } - - env.svgSupported = typeof SVGRect !== 'undefined'; - env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge; - env.pointerEventsSupported = 'onpointerdown' in window && (browser.edge || browser.ie && +browser.version >= 11); - env.domSupported = typeof document !== 'undefined'; - var style = document.documentElement.style; - env.transform3dSupported = (browser.ie && 'transition' in style || browser.edge || 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix() || 'MozPerspective' in style) && !('OTransition' in style); - env.transformSupported = env.transform3dSupported || browser.ie && +browser.version >= 9; - } - - var DEFAULT_FONT_SIZE = 12; - var DEFAULT_FONT_FAMILY = 'sans-serif'; - var DEFAULT_FONT = DEFAULT_FONT_SIZE + "px " + DEFAULT_FONT_FAMILY; - var OFFSET = 20; - var SCALE = 100; - var defaultWidthMapStr = "007LLmW'55;N0500LLLLLLLLLL00NNNLzWW\\\\WQb\\0FWLg\\bWb\\WQ\\WrWWQ000CL5LLFLL0LL**F*gLLLL5F0LF\\FFF5.5N"; - - function getTextWidthMap(mapStr) { - var map = {}; - - if (typeof JSON === 'undefined') { - return map; - } - - for (var i = 0; i < mapStr.length; i++) { - var char = String.fromCharCode(i + 32); - var size = (mapStr.charCodeAt(i) - OFFSET) / SCALE; - map[char] = size; - } - - return map; - } - - var DEFAULT_TEXT_WIDTH_MAP = getTextWidthMap(defaultWidthMapStr); - var platformApi = { - createCanvas: function () { - return typeof document !== 'undefined' && document.createElement('canvas'); - }, - measureText: function () { - var _ctx; - - var _cachedFont; - - return function (text, font) { - if (!_ctx) { - var canvas = platformApi.createCanvas(); - _ctx = canvas && canvas.getContext('2d'); - } - - if (_ctx) { - if (_cachedFont !== font) { - _cachedFont = _ctx.font = font || DEFAULT_FONT; - } - - return _ctx.measureText(text); - } else { - text = text || ''; - font = font || DEFAULT_FONT; - var res = /(\d+)px/.exec(font); - var fontSize = res && +res[1] || DEFAULT_FONT_SIZE; - var width = 0; - - if (font.indexOf('mono') >= 0) { - width = fontSize * text.length; - } else { - for (var i = 0; i < text.length; i++) { - var preCalcWidth = DEFAULT_TEXT_WIDTH_MAP[text[i]]; - width += preCalcWidth == null ? fontSize : preCalcWidth * fontSize; - } - } - - return { - width: width - }; - } - }; - }(), - loadImage: function (src, onload, onerror) { - var image = new Image(); - image.onload = onload; - image.onerror = onerror; - image.src = src; - return image; - } - }; - - function setPlatformAPI(newPlatformApis) { - for (var key in platformApi) { - if (newPlatformApis[key]) { - platformApi[key] = newPlatformApis[key]; - } - } - } - - var BUILTIN_OBJECT = reduce(['Function', 'RegExp', 'Date', 'Error', 'CanvasGradient', 'CanvasPattern', 'Image', 'Canvas'], function (obj, val) { - obj['[object ' + val + ']'] = true; - return obj; - }, {}); - var TYPED_ARRAY = reduce(['Int8', 'Uint8', 'Uint8Clamped', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Float32', 'Float64'], function (obj, val) { - obj['[object ' + val + 'Array]'] = true; - return obj; - }, {}); - var objToString = Object.prototype.toString; - var arrayProto = Array.prototype; - var nativeForEach = arrayProto.forEach; - var nativeFilter = arrayProto.filter; - var nativeSlice = arrayProto.slice; - var nativeMap = arrayProto.map; - - var ctorFunction = function () {}.constructor; - - var protoFunction = ctorFunction ? ctorFunction.prototype : null; - var protoKey = '__proto__'; - var idStart = 0x0907; - - function guid() { - return idStart++; - } - - function logError() { - var args = []; - - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - - if (typeof console !== 'undefined') { - console.error.apply(console, args); - } - } - - function clone$3(source) { - if (source == null || typeof source !== 'object') { - return source; - } - - var result = source; - var typeStr = objToString.call(source); - - if (typeStr === '[object Array]') { - if (!isPrimitive(source)) { - result = []; - - for (var i = 0, len = source.length; i < len; i++) { - result[i] = clone$3(source[i]); - } - } - } else if (TYPED_ARRAY[typeStr]) { - if (!isPrimitive(source)) { - var Ctor = source.constructor; - - if (Ctor.from) { - result = Ctor.from(source); - } else { - result = new Ctor(source.length); - - for (var i = 0, len = source.length; i < len; i++) { - result[i] = source[i]; - } - } - } - } else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { - result = {}; - - for (var key in source) { - if (source.hasOwnProperty(key) && key !== protoKey) { - result[key] = clone$3(source[key]); - } - } - } - - return result; - } - - function merge(target, source, overwrite) { - if (!isObject$2(source) || !isObject$2(target)) { - return overwrite ? clone$3(source) : target; - } - - for (var key in source) { - if (source.hasOwnProperty(key) && key !== protoKey) { - var targetProp = target[key]; - var sourceProp = source[key]; - - if (isObject$2(sourceProp) && isObject$2(targetProp) && !isArray(sourceProp) && !isArray(targetProp) && !isDom(sourceProp) && !isDom(targetProp) && !isBuiltInObject(sourceProp) && !isBuiltInObject(targetProp) && !isPrimitive(sourceProp) && !isPrimitive(targetProp)) { - merge(targetProp, sourceProp, overwrite); - } else if (overwrite || !(key in target)) { - target[key] = clone$3(source[key]); - } - } - } - - return target; - } - - function mergeAll(targetAndSources, overwrite) { - var result = targetAndSources[0]; - - for (var i = 1, len = targetAndSources.length; i < len; i++) { - result = merge(result, targetAndSources[i], overwrite); - } - - return result; - } - - function extend(target, source) { - if (Object.assign) { - Object.assign(target, source); - } else { - for (var key in source) { - if (source.hasOwnProperty(key) && key !== protoKey) { - target[key] = source[key]; - } - } - } - - return target; - } - - function defaults(target, source, overlay) { - var keysArr = keys(source); - - for (var i = 0; i < keysArr.length; i++) { - var key = keysArr[i]; - - if (overlay ? source[key] != null : target[key] == null) { - target[key] = source[key]; - } - } - - return target; - } - - var createCanvas = platformApi.createCanvas; - - function indexOf(array, value) { - if (array) { - if (array.indexOf) { - return array.indexOf(value); - } - - for (var i = 0, len = array.length; i < len; i++) { - if (array[i] === value) { - return i; - } - } - } - - return -1; - } - - function inherits(clazz, baseClazz) { - var clazzPrototype = clazz.prototype; - - function F() {} - - F.prototype = baseClazz.prototype; - clazz.prototype = new F(); - - for (var prop in clazzPrototype) { - if (clazzPrototype.hasOwnProperty(prop)) { - clazz.prototype[prop] = clazzPrototype[prop]; - } - } - - clazz.prototype.constructor = clazz; - clazz.superClass = baseClazz; - } - - function mixin(target, source, override) { - target = 'prototype' in target ? target.prototype : target; - source = 'prototype' in source ? source.prototype : source; - - if (Object.getOwnPropertyNames) { - var keyList = Object.getOwnPropertyNames(source); - - for (var i = 0; i < keyList.length; i++) { - var key = keyList[i]; - - if (key !== 'constructor') { - if (override ? source[key] != null : target[key] == null) { - target[key] = source[key]; - } - } - } - } else { - defaults(target, source, override); - } - } - - function isArrayLike(data) { - if (!data) { - return false; - } - - if (typeof data === 'string') { - return false; - } - - return typeof data.length === 'number'; - } - - function each$4(arr, cb, context) { - if (!(arr && cb)) { - return; - } - - if (arr.forEach && arr.forEach === nativeForEach) { - arr.forEach(cb, context); - } else if (arr.length === +arr.length) { - for (var i = 0, len = arr.length; i < len; i++) { - cb.call(context, arr[i], i, arr); - } - } else { - for (var key in arr) { - if (arr.hasOwnProperty(key)) { - cb.call(context, arr[key], key, arr); - } - } - } - } - - function map$1(arr, cb, context) { - if (!arr) { - return []; - } - - if (!cb) { - return slice(arr); - } - - if (arr.map && arr.map === nativeMap) { - return arr.map(cb, context); - } else { - var result = []; - - for (var i = 0, len = arr.length; i < len; i++) { - result.push(cb.call(context, arr[i], i, arr)); - } - - return result; - } - } - - function reduce(arr, cb, memo, context) { - if (!(arr && cb)) { - return; - } - - for (var i = 0, len = arr.length; i < len; i++) { - memo = cb.call(context, memo, arr[i], i, arr); - } - - return memo; - } - - function filter(arr, cb, context) { - if (!arr) { - return []; - } - - if (!cb) { - return slice(arr); - } - - if (arr.filter && arr.filter === nativeFilter) { - return arr.filter(cb, context); - } else { - var result = []; - - for (var i = 0, len = arr.length; i < len; i++) { - if (cb.call(context, arr[i], i, arr)) { - result.push(arr[i]); - } - } - - return result; - } - } - - function find(arr, cb, context) { - if (!(arr && cb)) { - return; - } - - for (var i = 0, len = arr.length; i < len; i++) { - if (cb.call(context, arr[i], i, arr)) { - return arr[i]; - } - } - } - - function keys(obj) { - if (!obj) { - return []; - } - - if (Object.keys) { - return Object.keys(obj); - } - - var keyList = []; - - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - keyList.push(key); - } - } - - return keyList; - } - - function bindPolyfill(func, context) { - var args = []; - - for (var _i = 2; _i < arguments.length; _i++) { - args[_i - 2] = arguments[_i]; - } - - return function () { - return func.apply(context, args.concat(nativeSlice.call(arguments))); - }; - } - - var bind$1 = protoFunction && isFunction(protoFunction.bind) ? protoFunction.call.bind(protoFunction.bind) : bindPolyfill; - - function curry$1(func) { - var args = []; - - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - - return function () { - return func.apply(this, args.concat(nativeSlice.call(arguments))); - }; - } - - function isArray(value) { - if (Array.isArray) { - return Array.isArray(value); - } - - return objToString.call(value) === '[object Array]'; - } - - function isFunction(value) { - return typeof value === 'function'; - } - - function isString(value) { - return typeof value === 'string'; - } - - function isStringSafe(value) { - return objToString.call(value) === '[object String]'; - } - - function isNumber(value) { - return typeof value === 'number'; - } - - function isObject$2(value) { - var type = typeof value; - return type === 'function' || !!value && type === 'object'; - } - - function isBuiltInObject(value) { - return !!BUILTIN_OBJECT[objToString.call(value)]; - } - - function isTypedArray(value) { - return !!TYPED_ARRAY[objToString.call(value)]; - } - - function isDom(value) { - return typeof value === 'object' && typeof value.nodeType === 'number' && typeof value.ownerDocument === 'object'; - } - - function isGradientObject(value) { - return value.colorStops != null; - } - - function isImagePatternObject(value) { - return value.image != null; - } - - function isRegExp(value) { - return objToString.call(value) === '[object RegExp]'; - } - - function eqNaN(value) { - return value !== value; - } - - function retrieve() { - var args = []; - - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - - for (var i = 0, len = args.length; i < len; i++) { - if (args[i] != null) { - return args[i]; - } - } - } - - function retrieve2(value0, value1) { - return value0 != null ? value0 : value1; - } - - function retrieve3(value0, value1, value2) { - return value0 != null ? value0 : value1 != null ? value1 : value2; - } - - function slice(arr) { - var args = []; - - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - - return nativeSlice.apply(arr, args); - } - - function normalizeCssArray$1(val) { - if (typeof val === 'number') { - return [val, val, val, val]; - } - - var len = val.length; - - if (len === 2) { - return [val[0], val[1], val[0], val[1]]; - } else if (len === 3) { - return [val[0], val[1], val[2], val[1]]; - } - - return val; - } - - function assert(condition, message) { - if (!condition) { - throw new Error(message); - } - } - - function trim(str) { - if (str == null) { - return null; - } else if (typeof str.trim === 'function') { - return str.trim(); - } else { - return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - } - } - - var primitiveKey = '__ec_primitive__'; - - function setAsPrimitive(obj) { - obj[primitiveKey] = true; - } - - function isPrimitive(obj) { - return obj[primitiveKey]; - } - - var MapPolyfill = function () { - function MapPolyfill() { - this.data = {}; - } - - MapPolyfill.prototype["delete"] = function (key) { - var existed = this.has(key); - - if (existed) { - delete this.data[key]; - } - - return existed; - }; - - MapPolyfill.prototype.has = function (key) { - return this.data.hasOwnProperty(key); - }; - - MapPolyfill.prototype.get = function (key) { - return this.data[key]; - }; - - MapPolyfill.prototype.set = function (key, value) { - this.data[key] = value; - return this; - }; - - MapPolyfill.prototype.keys = function () { - return keys(this.data); - }; - - MapPolyfill.prototype.forEach = function (callback) { - var data = this.data; - - for (var key in data) { - if (data.hasOwnProperty(key)) { - callback(data[key], key); - } - } - }; - - return MapPolyfill; - }(); - - var isNativeMapSupported = typeof Map === 'function'; - - function maybeNativeMap() { - return isNativeMapSupported ? new Map() : new MapPolyfill(); - } - - var HashMap = function () { - function HashMap(obj) { - var isArr = isArray(obj); - this.data = maybeNativeMap(); - var thisMap = this; - obj instanceof HashMap ? obj.each(visit) : obj && each$4(obj, visit); - - function visit(value, key) { - isArr ? thisMap.set(value, key) : thisMap.set(key, value); - } - } - - HashMap.prototype.hasKey = function (key) { - return this.data.has(key); - }; - - HashMap.prototype.get = function (key) { - return this.data.get(key); - }; - - HashMap.prototype.set = function (key, value) { - this.data.set(key, value); - return value; - }; - - HashMap.prototype.each = function (cb, context) { - this.data.forEach(function (value, key) { - cb.call(context, value, key); - }); - }; - - HashMap.prototype.keys = function () { - var keys = this.data.keys(); - return isNativeMapSupported ? Array.from(keys) : keys; - }; - - HashMap.prototype.removeKey = function (key) { - this.data["delete"](key); - }; - - return HashMap; - }(); - - function createHashMap(obj) { - return new HashMap(obj); - } - - function concatArray(a, b) { - var newArray = new a.constructor(a.length + b.length); - - for (var i = 0; i < a.length; i++) { - newArray[i] = a[i]; - } - - var offset = a.length; - - for (var i = 0; i < b.length; i++) { - newArray[i + offset] = b[i]; - } - - return newArray; - } - - function createObject(proto, properties) { - var obj; - - if (Object.create) { - obj = Object.create(proto); - } else { - var StyleCtor = function () {}; - - StyleCtor.prototype = proto; - obj = new StyleCtor(); - } - - if (properties) { - extend(obj, properties); - } - - return obj; - } - - function disableUserSelect(dom) { - var domStyle = dom.style; - domStyle.webkitUserSelect = 'none'; - domStyle.userSelect = 'none'; - domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)'; - domStyle['-webkit-touch-callout'] = 'none'; - } - - function hasOwn(own, prop) { - return own.hasOwnProperty(prop); - } - - function noop() {} - - var RADIAN_TO_DEGREE = 180 / Math.PI; - var util$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - HashMap: HashMap, - RADIAN_TO_DEGREE: RADIAN_TO_DEGREE, - assert: assert, - bind: bind$1, - clone: clone$3, - concatArray: concatArray, - createCanvas: createCanvas, - createHashMap: createHashMap, - createObject: createObject, - curry: curry$1, - defaults: defaults, - disableUserSelect: disableUserSelect, - each: each$4, - eqNaN: eqNaN, - extend: extend, - filter: filter, - find: find, - guid: guid, - hasOwn: hasOwn, - indexOf: indexOf, - inherits: inherits, - isArray: isArray, - isArrayLike: isArrayLike, - isBuiltInObject: isBuiltInObject, - isDom: isDom, - isFunction: isFunction, - isGradientObject: isGradientObject, - isImagePatternObject: isImagePatternObject, - isNumber: isNumber, - isObject: isObject$2, - isPrimitive: isPrimitive, - isRegExp: isRegExp, - isString: isString, - isStringSafe: isStringSafe, - isTypedArray: isTypedArray, - keys: keys, - logError: logError, - map: map$1, - merge: merge, - mergeAll: mergeAll, - mixin: mixin, - noop: noop, - normalizeCssArray: normalizeCssArray$1, - reduce: reduce, - retrieve: retrieve, - retrieve2: retrieve2, - retrieve3: retrieve3, - setAsPrimitive: setAsPrimitive, - slice: slice, - trim: trim - }); - - function create$1(x, y) { - if (x == null) { - x = 0; - } - - if (y == null) { - y = 0; - } - - return [x, y]; - } - - function copy$1(out, v) { - out[0] = v[0]; - out[1] = v[1]; - return out; - } - - function clone$2(v) { - return [v[0], v[1]]; - } - - function set$1(out, a, b) { - out[0] = a; - out[1] = b; - return out; - } - - function add(out, v1, v2) { - out[0] = v1[0] + v2[0]; - out[1] = v1[1] + v2[1]; - return out; - } - - function scaleAndAdd(out, v1, v2, a) { - out[0] = v1[0] + v2[0] * a; - out[1] = v1[1] + v2[1] * a; - return out; - } - - function sub(out, v1, v2) { - out[0] = v1[0] - v2[0]; - out[1] = v1[1] - v2[1]; - return out; - } - - function len(v) { - return Math.sqrt(lenSquare(v)); - } - - var length = len; - - function lenSquare(v) { - return v[0] * v[0] + v[1] * v[1]; - } - - var lengthSquare = lenSquare; - - function mul$1(out, v1, v2) { - out[0] = v1[0] * v2[0]; - out[1] = v1[1] * v2[1]; - return out; - } - - function div(out, v1, v2) { - out[0] = v1[0] / v2[0]; - out[1] = v1[1] / v2[1]; - return out; - } - - function dot(v1, v2) { - return v1[0] * v2[0] + v1[1] * v2[1]; - } - - function scale$2(out, v, s) { - out[0] = v[0] * s; - out[1] = v[1] * s; - return out; - } - - function normalize$1(out, v) { - var d = len(v); - - if (d === 0) { - out[0] = 0; - out[1] = 0; - } else { - out[0] = v[0] / d; - out[1] = v[1] / d; - } - - return out; - } - - function distance(v1, v2) { - return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1])); - } - - var dist$1 = distance; - - function distanceSquare(v1, v2) { - return (v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]); - } - - var distSquare = distanceSquare; - - function negate(out, v) { - out[0] = -v[0]; - out[1] = -v[1]; - return out; - } - - function lerp$1(out, v1, v2, t) { - out[0] = v1[0] + t * (v2[0] - v1[0]); - out[1] = v1[1] + t * (v2[1] - v1[1]); - return out; - } - - function applyTransform$1(out, v, m) { - var x = v[0]; - var y = v[1]; - out[0] = m[0] * x + m[2] * y + m[4]; - out[1] = m[1] * x + m[3] * y + m[5]; - return out; - } - - function min$1(out, v1, v2) { - out[0] = Math.min(v1[0], v2[0]); - out[1] = Math.min(v1[1], v2[1]); - return out; - } - - function max$1(out, v1, v2) { - out[0] = Math.max(v1[0], v2[0]); - out[1] = Math.max(v1[1], v2[1]); - return out; - } - - var vector = /*#__PURE__*/Object.freeze({ - __proto__: null, - add: add, - applyTransform: applyTransform$1, - clone: clone$2, - copy: copy$1, - create: create$1, - dist: dist$1, - distSquare: distSquare, - distance: distance, - distanceSquare: distanceSquare, - div: div, - dot: dot, - len: len, - lenSquare: lenSquare, - length: length, - lengthSquare: lengthSquare, - lerp: lerp$1, - max: max$1, - min: min$1, - mul: mul$1, - negate: negate, - normalize: normalize$1, - scale: scale$2, - scaleAndAdd: scaleAndAdd, - set: set$1, - sub: sub - }); - - var Param = function () { - function Param(target, e) { - this.target = target; - this.topTarget = e && e.topTarget; - } - - return Param; - }(); - - var Draggable = function () { - function Draggable(handler) { - this.handler = handler; - handler.on('mousedown', this._dragStart, this); - handler.on('mousemove', this._drag, this); - handler.on('mouseup', this._dragEnd, this); - } - - Draggable.prototype._dragStart = function (e) { - var draggingTarget = e.target; - - while (draggingTarget && !draggingTarget.draggable) { - draggingTarget = draggingTarget.parent || draggingTarget.__hostTarget; - } - - if (draggingTarget) { - this._draggingTarget = draggingTarget; - draggingTarget.dragging = true; - this._x = e.offsetX; - this._y = e.offsetY; - this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragstart', e.event); - } - }; - - Draggable.prototype._drag = function (e) { - var draggingTarget = this._draggingTarget; - - if (draggingTarget) { - var x = e.offsetX; - var y = e.offsetY; - var dx = x - this._x; - var dy = y - this._y; - this._x = x; - this._y = y; - draggingTarget.drift(dx, dy, e); - this.handler.dispatchToElement(new Param(draggingTarget, e), 'drag', e.event); - var dropTarget = this.handler.findHover(x, y, draggingTarget).target; - var lastDropTarget = this._dropTarget; - this._dropTarget = dropTarget; - - if (draggingTarget !== dropTarget) { - if (lastDropTarget && dropTarget !== lastDropTarget) { - this.handler.dispatchToElement(new Param(lastDropTarget, e), 'dragleave', e.event); - } - - if (dropTarget && dropTarget !== lastDropTarget) { - this.handler.dispatchToElement(new Param(dropTarget, e), 'dragenter', e.event); - } - } - } - }; - - Draggable.prototype._dragEnd = function (e) { - var draggingTarget = this._draggingTarget; - - if (draggingTarget) { - draggingTarget.dragging = false; - } - - this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragend', e.event); - - if (this._dropTarget) { - this.handler.dispatchToElement(new Param(this._dropTarget, e), 'drop', e.event); - } - - this._draggingTarget = null; - this._dropTarget = null; - }; - - return Draggable; - }(); - - var Eventful = function () { - function Eventful(eventProcessors) { - if (eventProcessors) { - this._$eventProcessor = eventProcessors; - } - } - - Eventful.prototype.on = function (event, query, handler, context) { - if (!this._$handlers) { - this._$handlers = {}; - } - - var _h = this._$handlers; - - if (typeof query === 'function') { - context = handler; - handler = query; - query = null; - } - - if (!handler || !event) { - return this; - } - - var eventProcessor = this._$eventProcessor; - - if (query != null && eventProcessor && eventProcessor.normalizeQuery) { - query = eventProcessor.normalizeQuery(query); - } - - if (!_h[event]) { - _h[event] = []; - } - - for (var i = 0; i < _h[event].length; i++) { - if (_h[event][i].h === handler) { - return this; - } - } - - var wrap = { - h: handler, - query: query, - ctx: context || this, - callAtLast: handler.zrEventfulCallAtLast - }; - var lastIndex = _h[event].length - 1; - var lastWrap = _h[event][lastIndex]; - lastWrap && lastWrap.callAtLast ? _h[event].splice(lastIndex, 0, wrap) : _h[event].push(wrap); - return this; - }; - - Eventful.prototype.isSilent = function (eventName) { - var _h = this._$handlers; - return !_h || !_h[eventName] || !_h[eventName].length; - }; - - Eventful.prototype.off = function (eventType, handler) { - var _h = this._$handlers; - - if (!_h) { - return this; - } - - if (!eventType) { - this._$handlers = {}; - return this; - } - - if (handler) { - if (_h[eventType]) { - var newList = []; - - for (var i = 0, l = _h[eventType].length; i < l; i++) { - if (_h[eventType][i].h !== handler) { - newList.push(_h[eventType][i]); - } - } - - _h[eventType] = newList; - } - - if (_h[eventType] && _h[eventType].length === 0) { - delete _h[eventType]; - } - } else { - delete _h[eventType]; - } - - return this; - }; - - Eventful.prototype.trigger = function (eventType) { - var args = []; - - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - - if (!this._$handlers) { - return this; - } - - var _h = this._$handlers[eventType]; - var eventProcessor = this._$eventProcessor; - - if (_h) { - var argLen = args.length; - var len = _h.length; - - for (var i = 0; i < len; i++) { - var hItem = _h[i]; - - if (eventProcessor && eventProcessor.filter && hItem.query != null && !eventProcessor.filter(eventType, hItem.query)) { - continue; - } - - switch (argLen) { - case 0: - hItem.h.call(hItem.ctx); - break; - - case 1: - hItem.h.call(hItem.ctx, args[0]); - break; - - case 2: - hItem.h.call(hItem.ctx, args[0], args[1]); - break; - - default: - hItem.h.apply(hItem.ctx, args); - break; - } - } - } - - eventProcessor && eventProcessor.afterTrigger && eventProcessor.afterTrigger(eventType); - return this; - }; - - Eventful.prototype.triggerWithContext = function (type) { - var args = []; - - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - - if (!this._$handlers) { - return this; - } - - var _h = this._$handlers[type]; - var eventProcessor = this._$eventProcessor; - - if (_h) { - var argLen = args.length; - var ctx = args[argLen - 1]; - var len = _h.length; - - for (var i = 0; i < len; i++) { - var hItem = _h[i]; - - if (eventProcessor && eventProcessor.filter && hItem.query != null && !eventProcessor.filter(type, hItem.query)) { - continue; - } - - switch (argLen) { - case 0: - hItem.h.call(ctx); - break; - - case 1: - hItem.h.call(ctx, args[0]); - break; - - case 2: - hItem.h.call(ctx, args[0], args[1]); - break; - - default: - hItem.h.apply(ctx, args.slice(1, argLen - 1)); - break; - } - } - } - - eventProcessor && eventProcessor.afterTrigger && eventProcessor.afterTrigger(type); - return this; - }; - - return Eventful; - }(); - - var LN2 = Math.log(2); - - function determinant(rows, rank, rowStart, rowMask, colMask, detCache) { - var cacheKey = rowMask + '-' + colMask; - var fullRank = rows.length; - - if (detCache.hasOwnProperty(cacheKey)) { - return detCache[cacheKey]; - } - - if (rank === 1) { - var colStart = Math.round(Math.log((1 << fullRank) - 1 & ~colMask) / LN2); - return rows[rowStart][colStart]; - } - - var subRowMask = rowMask | 1 << rowStart; - var subRowStart = rowStart + 1; - - while (rowMask & 1 << subRowStart) { - subRowStart++; - } - - var sum = 0; - - for (var j = 0, colLocalIdx = 0; j < fullRank; j++) { - var colTag = 1 << j; - - if (!(colTag & colMask)) { - sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j] * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache); - colLocalIdx++; - } - } - - detCache[cacheKey] = sum; - return sum; - } - - function buildTransformer(src, dest) { - var mA = [[src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]], [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]], [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]], [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]], [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]], [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]], [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]], [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]]]; - var detCache = {}; - var det = determinant(mA, 8, 0, 0, 0, detCache); - - if (det === 0) { - return; - } - - var vh = []; - - for (var i = 0; i < 8; i++) { - for (var j = 0; j < 8; j++) { - vh[j] == null && (vh[j] = 0); - vh[j] += ((i + j) % 2 ? -1 : 1) * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache) / det * dest[i]; - } - } - - return function (out, srcPointX, srcPointY) { - var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1; - out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk; - out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk; - }; - } - - var EVENT_SAVED_PROP = '___zrEVENTSAVED'; - var _calcOut$1 = []; - - function transformLocalCoord(out, elFrom, elTarget, inX, inY) { - return transformCoordWithViewport(_calcOut$1, elFrom, inX, inY, true) && transformCoordWithViewport(out, elTarget, _calcOut$1[0], _calcOut$1[1]); - } - - function transformCoordWithViewport(out, el, inX, inY, inverse) { - if (el.getBoundingClientRect && env.domSupported && !isCanvasEl(el)) { - var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {}); - var markers = prepareCoordMarkers(el, saved); - var transformer = preparePointerTransformer(markers, saved, inverse); - - if (transformer) { - transformer(out, inX, inY); - return true; - } - } - - return false; - } - - function prepareCoordMarkers(el, saved) { - var markers = saved.markers; - - if (markers) { - return markers; - } - - markers = saved.markers = []; - var propLR = ['left', 'right']; - var propTB = ['top', 'bottom']; - - for (var i = 0; i < 4; i++) { - var marker = document.createElement('div'); - var stl = marker.style; - var idxLR = i % 2; - var idxTB = (i >> 1) % 2; - stl.cssText = ['position: absolute', 'visibility: hidden', 'padding: 0', 'margin: 0', 'border-width: 0', 'user-select: none', 'width:0', 'height:0', propLR[idxLR] + ':0', propTB[idxTB] + ':0', propLR[1 - idxLR] + ':auto', propTB[1 - idxTB] + ':auto', ''].join('!important;'); - el.appendChild(marker); - markers.push(marker); - } - - return markers; - } - - function preparePointerTransformer(markers, saved, inverse) { - var transformerName = inverse ? 'invTrans' : 'trans'; - var transformer = saved[transformerName]; - var oldSrcCoords = saved.srcCoords; - var srcCoords = []; - var destCoords = []; - var oldCoordTheSame = true; - - for (var i = 0; i < 4; i++) { - var rect = markers[i].getBoundingClientRect(); - var ii = 2 * i; - var x = rect.left; - var y = rect.top; - srcCoords.push(x, y); - oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1]; - destCoords.push(markers[i].offsetLeft, markers[i].offsetTop); - } - - return oldCoordTheSame && transformer ? transformer : (saved.srcCoords = srcCoords, saved[transformerName] = inverse ? buildTransformer(destCoords, srcCoords) : buildTransformer(srcCoords, destCoords)); - } - - function isCanvasEl(el) { - return el.nodeName.toUpperCase() === 'CANVAS'; - } - - var replaceReg = /([&<>"'])/g; - var replaceMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - '\'': ''' - }; - - function encodeHTML(source) { - return source == null ? '' : (source + '').replace(replaceReg, function (str, c) { - return replaceMap[c]; - }); - } - - var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/; - var _calcOut = []; - var firefoxNotSupportOffsetXY = env.browser.firefox && +env.browser.version.split('.')[0] < 39; - - function clientToLocal(el, e, out, calculate) { - out = out || {}; - - if (calculate) { - calculateZrXY(el, e, out); - } else if (firefoxNotSupportOffsetXY && e.layerX != null && e.layerX !== e.offsetX) { - out.zrX = e.layerX; - out.zrY = e.layerY; - } else if (e.offsetX != null) { - out.zrX = e.offsetX; - out.zrY = e.offsetY; - } else { - calculateZrXY(el, e, out); - } - - return out; - } - - function calculateZrXY(el, e, out) { - if (env.domSupported && el.getBoundingClientRect) { - var ex = e.clientX; - var ey = e.clientY; - - if (isCanvasEl(el)) { - var box = el.getBoundingClientRect(); - out.zrX = ex - box.left; - out.zrY = ey - box.top; - return; - } else { - if (transformCoordWithViewport(_calcOut, el, ex, ey)) { - out.zrX = _calcOut[0]; - out.zrY = _calcOut[1]; - return; - } - } - } - - out.zrX = out.zrY = 0; - } - - function getNativeEvent(e) { - return e || window.event; - } - - function normalizeEvent(el, e, calculate) { - e = getNativeEvent(e); - - if (e.zrX != null) { - return e; - } - - var eventType = e.type; - var isTouch = eventType && eventType.indexOf('touch') >= 0; - - if (!isTouch) { - clientToLocal(el, e, e, calculate); - var wheelDelta = getWheelDeltaMayPolyfill(e); - e.zrDelta = wheelDelta ? wheelDelta / 120 : -(e.detail || 0) / 3; - } else { - var touch = eventType !== 'touchend' ? e.targetTouches[0] : e.changedTouches[0]; - touch && clientToLocal(el, touch, e, calculate); - } - - var button = e.button; - - if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) { - e.which = button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0; - } - - return e; - } - - function getWheelDeltaMayPolyfill(e) { - var rawWheelDelta = e.wheelDelta; - - if (rawWheelDelta) { - return rawWheelDelta; - } - - var deltaX = e.deltaX; - var deltaY = e.deltaY; - - if (deltaX == null || deltaY == null) { - return rawWheelDelta; - } - - var delta = deltaY !== 0 ? Math.abs(deltaY) : Math.abs(deltaX); - var sign = deltaY > 0 ? -1 : deltaY < 0 ? 1 : deltaX > 0 ? -1 : 1; - return 3 * delta * sign; - } - - function addEventListener(el, name, handler, opt) { - el.addEventListener(name, handler, opt); - } - - function removeEventListener(el, name, handler, opt) { - el.removeEventListener(name, handler, opt); - } - - var stop = function (e) { - e.preventDefault(); - e.stopPropagation(); - e.cancelBubble = true; - }; - - var GestureMgr = function () { - function GestureMgr() { - this._track = []; - } - - GestureMgr.prototype.recognize = function (event, target, root) { - this._doTrack(event, target, root); - - return this._recognize(event); - }; - - GestureMgr.prototype.clear = function () { - this._track.length = 0; - return this; - }; - - GestureMgr.prototype._doTrack = function (event, target, root) { - var touches = event.touches; - - if (!touches) { - return; - } - - var trackItem = { - points: [], - touches: [], - target: target, - event: event - }; - - for (var i = 0, len = touches.length; i < len; i++) { - var touch = touches[i]; - var pos = clientToLocal(root, touch, {}); - trackItem.points.push([pos.zrX, pos.zrY]); - trackItem.touches.push(touch); - } - - this._track.push(trackItem); - }; - - GestureMgr.prototype._recognize = function (event) { - for (var eventName in recognizers) { - if (recognizers.hasOwnProperty(eventName)) { - var gestureInfo = recognizers[eventName](this._track, event); - - if (gestureInfo) { - return gestureInfo; - } - } - } - }; - - return GestureMgr; - }(); - - function dist(pointPair) { - var dx = pointPair[1][0] - pointPair[0][0]; - var dy = pointPair[1][1] - pointPair[0][1]; - return Math.sqrt(dx * dx + dy * dy); - } - - function center(pointPair) { - return [(pointPair[0][0] + pointPair[1][0]) / 2, (pointPair[0][1] + pointPair[1][1]) / 2]; - } - - var recognizers = { - pinch: function (tracks, event) { - var trackLen = tracks.length; - - if (!trackLen) { - return; - } - - var pinchEnd = (tracks[trackLen - 1] || {}).points; - var pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd; - - if (pinchPre && pinchPre.length > 1 && pinchEnd && pinchEnd.length > 1) { - var pinchScale = dist(pinchEnd) / dist(pinchPre); - !isFinite(pinchScale) && (pinchScale = 1); - event.pinchScale = pinchScale; - var pinchCenter = center(pinchEnd); - event.pinchX = pinchCenter[0]; - event.pinchY = pinchCenter[1]; - return { - type: 'pinch', - target: tracks[0].target, - event: event - }; - } - } - }; - - function create() { - return [1, 0, 0, 1, 0, 0]; - } - - function identity(out) { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 1; - out[4] = 0; - out[5] = 0; - return out; - } - - function copy(out, m) { - out[0] = m[0]; - out[1] = m[1]; - out[2] = m[2]; - out[3] = m[3]; - out[4] = m[4]; - out[5] = m[5]; - return out; - } - - function mul(out, m1, m2) { - var out0 = m1[0] * m2[0] + m1[2] * m2[1]; - var out1 = m1[1] * m2[0] + m1[3] * m2[1]; - var out2 = m1[0] * m2[2] + m1[2] * m2[3]; - var out3 = m1[1] * m2[2] + m1[3] * m2[3]; - var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; - var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; - out[0] = out0; - out[1] = out1; - out[2] = out2; - out[3] = out3; - out[4] = out4; - out[5] = out5; - return out; - } - - function translate(out, a, v) { - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - out[4] = a[4] + v[0]; - out[5] = a[5] + v[1]; - return out; - } - - function rotate(out, a, rad, pivot) { - if (pivot === void 0) { - pivot = [0, 0]; - } - - var aa = a[0]; - var ac = a[2]; - var atx = a[4]; - var ab = a[1]; - var ad = a[3]; - var aty = a[5]; - var st = Math.sin(rad); - var ct = Math.cos(rad); - out[0] = aa * ct + ab * st; - out[1] = -aa * st + ab * ct; - out[2] = ac * ct + ad * st; - out[3] = -ac * st + ct * ad; - out[4] = ct * (atx - pivot[0]) + st * (aty - pivot[1]) + pivot[0]; - out[5] = ct * (aty - pivot[1]) - st * (atx - pivot[0]) + pivot[1]; - return out; - } - - function scale$1(out, a, v) { - var vx = v[0]; - var vy = v[1]; - out[0] = a[0] * vx; - out[1] = a[1] * vy; - out[2] = a[2] * vx; - out[3] = a[3] * vy; - out[4] = a[4] * vx; - out[5] = a[5] * vy; - return out; - } - - function invert(out, a) { - var aa = a[0]; - var ac = a[2]; - var atx = a[4]; - var ab = a[1]; - var ad = a[3]; - var aty = a[5]; - var det = aa * ad - ab * ac; - - if (!det) { - return null; - } - - det = 1.0 / det; - out[0] = ad * det; - out[1] = -ab * det; - out[2] = -ac * det; - out[3] = aa * det; - out[4] = (ac * aty - ad * atx) * det; - out[5] = (ab * atx - aa * aty) * det; - return out; - } - - function clone$1(a) { - var b = create(); - copy(b, a); - return b; - } - - var matrix = /*#__PURE__*/Object.freeze({ - __proto__: null, - clone: clone$1, - copy: copy, - create: create, - identity: identity, - invert: invert, - mul: mul, - rotate: rotate, - scale: scale$1, - translate: translate - }); - - var Point = function () { - function Point(x, y) { - this.x = x || 0; - this.y = y || 0; - } - - Point.prototype.copy = function (other) { - this.x = other.x; - this.y = other.y; - return this; - }; - - Point.prototype.clone = function () { - return new Point(this.x, this.y); - }; - - Point.prototype.set = function (x, y) { - this.x = x; - this.y = y; - return this; - }; - - Point.prototype.equal = function (other) { - return other.x === this.x && other.y === this.y; - }; - - Point.prototype.add = function (other) { - this.x += other.x; - this.y += other.y; - return this; - }; - - Point.prototype.scale = function (scalar) { - this.x *= scalar; - this.y *= scalar; - }; - - Point.prototype.scaleAndAdd = function (other, scalar) { - this.x += other.x * scalar; - this.y += other.y * scalar; - }; - - Point.prototype.sub = function (other) { - this.x -= other.x; - this.y -= other.y; - return this; - }; - - Point.prototype.dot = function (other) { - return this.x * other.x + this.y * other.y; - }; - - Point.prototype.len = function () { - return Math.sqrt(this.x * this.x + this.y * this.y); - }; - - Point.prototype.lenSquare = function () { - return this.x * this.x + this.y * this.y; - }; - - Point.prototype.normalize = function () { - var len = this.len(); - this.x /= len; - this.y /= len; - return this; - }; - - Point.prototype.distance = function (other) { - var dx = this.x - other.x; - var dy = this.y - other.y; - return Math.sqrt(dx * dx + dy * dy); - }; - - Point.prototype.distanceSquare = function (other) { - var dx = this.x - other.x; - var dy = this.y - other.y; - return dx * dx + dy * dy; - }; - - Point.prototype.negate = function () { - this.x = -this.x; - this.y = -this.y; - return this; - }; - - Point.prototype.transform = function (m) { - if (!m) { - return; - } - - var x = this.x; - var y = this.y; - this.x = m[0] * x + m[2] * y + m[4]; - this.y = m[1] * x + m[3] * y + m[5]; - return this; - }; - - Point.prototype.toArray = function (out) { - out[0] = this.x; - out[1] = this.y; - return out; - }; - - Point.prototype.fromArray = function (input) { - this.x = input[0]; - this.y = input[1]; - }; - - Point.set = function (p, x, y) { - p.x = x; - p.y = y; - }; - - Point.copy = function (p, p2) { - p.x = p2.x; - p.y = p2.y; - }; - - Point.len = function (p) { - return Math.sqrt(p.x * p.x + p.y * p.y); - }; - - Point.lenSquare = function (p) { - return p.x * p.x + p.y * p.y; - }; - - Point.dot = function (p0, p1) { - return p0.x * p1.x + p0.y * p1.y; - }; - - Point.add = function (out, p0, p1) { - out.x = p0.x + p1.x; - out.y = p0.y + p1.y; - }; - - Point.sub = function (out, p0, p1) { - out.x = p0.x - p1.x; - out.y = p0.y - p1.y; - }; - - Point.scale = function (out, p0, scalar) { - out.x = p0.x * scalar; - out.y = p0.y * scalar; - }; - - Point.scaleAndAdd = function (out, p0, p1, scalar) { - out.x = p0.x + p1.x * scalar; - out.y = p0.y + p1.y * scalar; - }; - - Point.lerp = function (out, p0, p1, t) { - var onet = 1 - t; - out.x = onet * p0.x + t * p1.x; - out.y = onet * p0.y + t * p1.y; - }; - - return Point; - }(); - - var mathMin$6 = Math.min; - var mathMax$6 = Math.max; - var lt = new Point(); - var rb = new Point(); - var lb = new Point(); - var rt = new Point(); - var minTv$1 = new Point(); - var maxTv$1 = new Point(); - - var BoundingRect = function () { - function BoundingRect(x, y, width, height) { - if (width < 0) { - x = x + width; - width = -width; - } - - if (height < 0) { - y = y + height; - height = -height; - } - - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - BoundingRect.prototype.union = function (other) { - var x = mathMin$6(other.x, this.x); - var y = mathMin$6(other.y, this.y); - - if (isFinite(this.x) && isFinite(this.width)) { - this.width = mathMax$6(other.x + other.width, this.x + this.width) - x; - } else { - this.width = other.width; - } - - if (isFinite(this.y) && isFinite(this.height)) { - this.height = mathMax$6(other.y + other.height, this.y + this.height) - y; - } else { - this.height = other.height; - } - - this.x = x; - this.y = y; - }; - - BoundingRect.prototype.applyTransform = function (m) { - BoundingRect.applyTransform(this, this, m); - }; - - BoundingRect.prototype.calculateTransform = function (b) { - var a = this; - var sx = b.width / a.width; - var sy = b.height / a.height; - var m = create(); - translate(m, m, [-a.x, -a.y]); - scale$1(m, m, [sx, sy]); - translate(m, m, [b.x, b.y]); - return m; - }; - - BoundingRect.prototype.intersect = function (b, mtv) { - if (!b) { - return false; - } - - if (!(b instanceof BoundingRect)) { - b = BoundingRect.create(b); - } - - var a = this; - var ax0 = a.x; - var ax1 = a.x + a.width; - var ay0 = a.y; - var ay1 = a.y + a.height; - var bx0 = b.x; - var bx1 = b.x + b.width; - var by0 = b.y; - var by1 = b.y + b.height; - var overlap = !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); - - if (mtv) { - var dMin = Infinity; - var dMax = 0; - var d0 = Math.abs(ax1 - bx0); - var d1 = Math.abs(bx1 - ax0); - var d2 = Math.abs(ay1 - by0); - var d3 = Math.abs(by1 - ay0); - var dx = Math.min(d0, d1); - var dy = Math.min(d2, d3); - - if (ax1 < bx0 || bx1 < ax0) { - if (dx > dMax) { - dMax = dx; - - if (d0 < d1) { - Point.set(maxTv$1, -d0, 0); - } else { - Point.set(maxTv$1, d1, 0); - } - } - } else { - if (dx < dMin) { - dMin = dx; - - if (d0 < d1) { - Point.set(minTv$1, d0, 0); - } else { - Point.set(minTv$1, -d1, 0); - } - } - } - - if (ay1 < by0 || by1 < ay0) { - if (dy > dMax) { - dMax = dy; - - if (d2 < d3) { - Point.set(maxTv$1, 0, -d2); - } else { - Point.set(maxTv$1, 0, d3); - } - } - } else { - if (dx < dMin) { - dMin = dx; - - if (d2 < d3) { - Point.set(minTv$1, 0, d2); - } else { - Point.set(minTv$1, 0, -d3); - } - } - } - } - - if (mtv) { - Point.copy(mtv, overlap ? minTv$1 : maxTv$1); - } - - return overlap; - }; - - BoundingRect.prototype.contain = function (x, y) { - var rect = this; - return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height; - }; - - BoundingRect.prototype.clone = function () { - return new BoundingRect(this.x, this.y, this.width, this.height); - }; - - BoundingRect.prototype.copy = function (other) { - BoundingRect.copy(this, other); - }; - - BoundingRect.prototype.plain = function () { - return { - x: this.x, - y: this.y, - width: this.width, - height: this.height - }; - }; - - BoundingRect.prototype.isFinite = function () { - return isFinite(this.x) && isFinite(this.y) && isFinite(this.width) && isFinite(this.height); - }; - - BoundingRect.prototype.isZero = function () { - return this.width === 0 || this.height === 0; - }; - - BoundingRect.create = function (rect) { - return new BoundingRect(rect.x, rect.y, rect.width, rect.height); - }; - - BoundingRect.copy = function (target, source) { - target.x = source.x; - target.y = source.y; - target.width = source.width; - target.height = source.height; - }; - - BoundingRect.applyTransform = function (target, source, m) { - if (!m) { - if (target !== source) { - BoundingRect.copy(target, source); - } - - return; - } - - if (m[1] < 1e-5 && m[1] > -1e-5 && m[2] < 1e-5 && m[2] > -1e-5) { - var sx = m[0]; - var sy = m[3]; - var tx = m[4]; - var ty = m[5]; - target.x = source.x * sx + tx; - target.y = source.y * sy + ty; - target.width = source.width * sx; - target.height = source.height * sy; - - if (target.width < 0) { - target.x += target.width; - target.width = -target.width; - } - - if (target.height < 0) { - target.y += target.height; - target.height = -target.height; - } - - return; - } - - lt.x = lb.x = source.x; - lt.y = rt.y = source.y; - rb.x = rt.x = source.x + source.width; - rb.y = lb.y = source.y + source.height; - lt.transform(m); - rt.transform(m); - rb.transform(m); - lb.transform(m); - target.x = mathMin$6(lt.x, rb.x, lb.x, rt.x); - target.y = mathMin$6(lt.y, rb.y, lb.y, rt.y); - var maxX = mathMax$6(lt.x, rb.x, lb.x, rt.x); - var maxY = mathMax$6(lt.y, rb.y, lb.y, rt.y); - target.width = maxX - target.x; - target.height = maxY - target.y; - }; - - return BoundingRect; - }(); - - var SILENT = 'silent'; - - function makeEventPacket(eveType, targetInfo, event) { - return { - type: eveType, - event: event, - target: targetInfo.target, - topTarget: targetInfo.topTarget, - cancelBubble: false, - offsetX: event.zrX, - offsetY: event.zrY, - gestureEvent: event.gestureEvent, - pinchX: event.pinchX, - pinchY: event.pinchY, - pinchScale: event.pinchScale, - wheelDelta: event.zrDelta, - zrByTouch: event.zrByTouch, - which: event.which, - stop: stopEvent - }; - } - - function stopEvent() { - stop(this.event); - } - - var EmptyProxy = function (_super) { - __extends(EmptyProxy, _super); - - function EmptyProxy() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.handler = null; - return _this; - } - - EmptyProxy.prototype.dispose = function () {}; - - EmptyProxy.prototype.setCursor = function () {}; - - return EmptyProxy; - }(Eventful); - - var HoveredResult = function () { - function HoveredResult(x, y) { - this.x = x; - this.y = y; - } - - return HoveredResult; - }(); - - var handlerNames = ['click', 'dblclick', 'mousewheel', 'mouseout', 'mouseup', 'mousedown', 'mousemove', 'contextmenu']; - var tmpRect$1 = new BoundingRect(0, 0, 0, 0); - - var Handler = function (_super) { - __extends(Handler, _super); - - function Handler(storage, painter, proxy, painterRoot, pointerSize) { - var _this = _super.call(this) || this; - - _this._hovered = new HoveredResult(0, 0); - _this.storage = storage; - _this.painter = painter; - _this.painterRoot = painterRoot; - _this._pointerSize = pointerSize; - proxy = proxy || new EmptyProxy(); - _this.proxy = null; - - _this.setHandlerProxy(proxy); - - _this._draggingMgr = new Draggable(_this); - return _this; - } - - Handler.prototype.setHandlerProxy = function (proxy) { - if (this.proxy) { - this.proxy.dispose(); - } - - if (proxy) { - each$4(handlerNames, function (name) { - proxy.on && proxy.on(name, this[name], this); - }, this); - proxy.handler = this; - } - - this.proxy = proxy; - }; - - Handler.prototype.mousemove = function (event) { - var x = event.zrX; - var y = event.zrY; - var isOutside = isOutsideBoundary(this, x, y); - var lastHovered = this._hovered; - var lastHoveredTarget = lastHovered.target; - - if (lastHoveredTarget && !lastHoveredTarget.__zr) { - lastHovered = this.findHover(lastHovered.x, lastHovered.y); - lastHoveredTarget = lastHovered.target; - } - - var hovered = this._hovered = isOutside ? new HoveredResult(x, y) : this.findHover(x, y); - var hoveredTarget = hovered.target; - var proxy = this.proxy; - proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default'); - - if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) { - this.dispatchToElement(lastHovered, 'mouseout', event); - } - - this.dispatchToElement(hovered, 'mousemove', event); - - if (hoveredTarget && hoveredTarget !== lastHoveredTarget) { - this.dispatchToElement(hovered, 'mouseover', event); - } - }; - - Handler.prototype.mouseout = function (event) { - var eventControl = event.zrEventControl; - - if (eventControl !== 'only_globalout') { - this.dispatchToElement(this._hovered, 'mouseout', event); - } - - if (eventControl !== 'no_globalout') { - this.trigger('globalout', { - type: 'globalout', - event: event - }); - } - }; - - Handler.prototype.resize = function () { - this._hovered = new HoveredResult(0, 0); - }; - - Handler.prototype.dispatch = function (eventName, eventArgs) { - var handler = this[eventName]; - handler && handler.call(this, eventArgs); - }; - - Handler.prototype.dispose = function () { - this.proxy.dispose(); - this.storage = null; - this.proxy = null; - this.painter = null; - }; - - Handler.prototype.setCursorStyle = function (cursorStyle) { - var proxy = this.proxy; - proxy.setCursor && proxy.setCursor(cursorStyle); - }; - - Handler.prototype.dispatchToElement = function (targetInfo, eventName, event) { - targetInfo = targetInfo || {}; - var el = targetInfo.target; - - if (el && el.silent) { - return; - } - - var eventKey = 'on' + eventName; - var eventPacket = makeEventPacket(eventName, targetInfo, event); - - while (el) { - el[eventKey] && (eventPacket.cancelBubble = !!el[eventKey].call(el, eventPacket)); - el.trigger(eventName, eventPacket); - el = el.__hostTarget ? el.__hostTarget : el.parent; - - if (eventPacket.cancelBubble) { - break; - } - } - - if (!eventPacket.cancelBubble) { - this.trigger(eventName, eventPacket); - - if (this.painter && this.painter.eachOtherLayer) { - this.painter.eachOtherLayer(function (layer) { - if (typeof layer[eventKey] === 'function') { - layer[eventKey].call(layer, eventPacket); - } - - if (layer.trigger) { - layer.trigger(eventName, eventPacket); - } - }); - } - } - }; - - Handler.prototype.findHover = function (x, y, exclude) { - var list = this.storage.getDisplayList(); - var out = new HoveredResult(x, y); - setHoverTarget(list, out, x, y, exclude); - - if (this._pointerSize && !out.target) { - var candidates = []; - var pointerSize = this._pointerSize; - var targetSizeHalf = pointerSize / 2; - var pointerRect = new BoundingRect(x - targetSizeHalf, y - targetSizeHalf, pointerSize, pointerSize); - - for (var i = list.length - 1; i >= 0; i--) { - var el = list[i]; - - if (el !== exclude && !el.ignore && !el.ignoreCoarsePointer && (!el.parent || !el.parent.ignoreCoarsePointer)) { - tmpRect$1.copy(el.getBoundingRect()); - - if (el.transform) { - tmpRect$1.applyTransform(el.transform); - } - - if (tmpRect$1.intersect(pointerRect)) { - candidates.push(el); - } - } - } - - if (candidates.length) { - var rStep = 4; - var thetaStep = Math.PI / 12; - var PI2 = Math.PI * 2; - - for (var r = 0; r < targetSizeHalf; r += rStep) { - for (var theta = 0; theta < PI2; theta += thetaStep) { - var x1 = x + r * Math.cos(theta); - var y1 = y + r * Math.sin(theta); - setHoverTarget(candidates, out, x1, y1, exclude); - - if (out.target) { - return out; - } - } - } - } - } - - return out; - }; - - Handler.prototype.processGesture = function (event, stage) { - if (!this._gestureMgr) { - this._gestureMgr = new GestureMgr(); - } - - var gestureMgr = this._gestureMgr; - stage === 'start' && gestureMgr.clear(); - var gestureInfo = gestureMgr.recognize(event, this.findHover(event.zrX, event.zrY, null).target, this.proxy.dom); - stage === 'end' && gestureMgr.clear(); - - if (gestureInfo) { - var type = gestureInfo.type; - event.gestureEvent = type; - var res = new HoveredResult(); - res.target = gestureInfo.target; - this.dispatchToElement(res, type, gestureInfo.event); - } - }; - - return Handler; - }(Eventful); - - each$4(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { - Handler.prototype[name] = function (event) { - var x = event.zrX; - var y = event.zrY; - var isOutside = isOutsideBoundary(this, x, y); - var hovered; - var hoveredTarget; - - if (name !== 'mouseup' || !isOutside) { - hovered = this.findHover(x, y); - hoveredTarget = hovered.target; - } - - if (name === 'mousedown') { - this._downEl = hoveredTarget; - this._downPoint = [event.zrX, event.zrY]; - this._upEl = hoveredTarget; - } else if (name === 'mouseup') { - this._upEl = hoveredTarget; - } else if (name === 'click') { - if (this._downEl !== this._upEl || !this._downPoint || dist$1(this._downPoint, [event.zrX, event.zrY]) > 4) { - return; - } - - this._downPoint = null; - } - - this.dispatchToElement(hovered, name, event); - }; - }); - - function isHover(displayable, x, y) { - if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) { - var el = displayable; - var isSilent = void 0; - var ignoreClip = false; - - while (el) { - if (el.ignoreClip) { - ignoreClip = true; - } - - if (!ignoreClip) { - var clipPath = el.getClipPath(); - - if (clipPath && !clipPath.contain(x, y)) { - return false; - } - } - - if (el.silent) { - isSilent = true; - } - - var hostEl = el.__hostTarget; - el = hostEl ? hostEl : el.parent; - } - - return isSilent ? SILENT : true; - } - - return false; - } - - function setHoverTarget(list, out, x, y, exclude) { - for (var i = list.length - 1; i >= 0; i--) { - var el = list[i]; - var hoverCheckResult = void 0; - - if (el !== exclude && !el.ignore && (hoverCheckResult = isHover(el, x, y))) { - !out.topTarget && (out.topTarget = el); - - if (hoverCheckResult !== SILENT) { - out.target = el; - break; - } - } - } - } - - function isOutsideBoundary(handlerInstance, x, y) { - var painter = handlerInstance.painter; - return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight(); - } - - var DEFAULT_MIN_MERGE = 32; - var DEFAULT_MIN_GALLOPING = 7; - - function minRunLength(n) { - var r = 0; - - while (n >= DEFAULT_MIN_MERGE) { - r |= n & 1; - n >>= 1; - } - - return n + r; - } - - function makeAscendingRun(array, lo, hi, compare) { - var runHi = lo + 1; - - if (runHi === hi) { - return 1; - } - - if (compare(array[runHi++], array[lo]) < 0) { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { - runHi++; - } - - reverseRun(array, lo, runHi); - } else { - while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { - runHi++; - } - } - - return runHi - lo; - } - - function reverseRun(array, lo, hi) { - hi--; - - while (lo < hi) { - var t = array[lo]; - array[lo++] = array[hi]; - array[hi--] = t; - } - } - - function binaryInsertionSort(array, lo, hi, start, compare) { - if (start === lo) { - start++; - } - - for (; start < hi; start++) { - var pivot = array[start]; - var left = lo; - var right = start; - var mid; - - while (left < right) { - mid = left + right >>> 1; - - if (compare(pivot, array[mid]) < 0) { - right = mid; - } else { - left = mid + 1; - } - } - - var n = start - left; - - switch (n) { - case 3: - array[left + 3] = array[left + 2]; - - case 2: - array[left + 2] = array[left + 1]; - - case 1: - array[left + 1] = array[left]; - break; - - default: - while (n > 0) { - array[left + n] = array[left + n - 1]; - n--; - } - - } - - array[left] = pivot; - } - } - - function gallopLeft(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) > 0) { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - lastOffset += hint; - offset += hint; - } else { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } - - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + (offset - lastOffset >>> 1); - - if (compare(value, array[start + m]) > 0) { - lastOffset = m + 1; - } else { - offset = m; - } - } - - return offset; - } - - function gallopRight(value, array, start, length, hint, compare) { - var lastOffset = 0; - var maxOffset = 0; - var offset = 1; - - if (compare(value, array[start + hint]) < 0) { - maxOffset = hint + 1; - - while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - var tmp = lastOffset; - lastOffset = hint - offset; - offset = hint - tmp; - } else { - maxOffset = length - hint; - - while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { - lastOffset = offset; - offset = (offset << 1) + 1; - - if (offset <= 0) { - offset = maxOffset; - } - } - - if (offset > maxOffset) { - offset = maxOffset; - } - - lastOffset += hint; - offset += hint; - } - - lastOffset++; - - while (lastOffset < offset) { - var m = lastOffset + (offset - lastOffset >>> 1); - - if (compare(value, array[start + m]) < 0) { - offset = m; - } else { - lastOffset = m + 1; - } - } - - return offset; - } - - function TimSort(array, compare) { - var minGallop = DEFAULT_MIN_GALLOPING; - var runStart; - var runLength; - var stackSize = 0; - var tmp = []; - runStart = []; - runLength = []; - - function pushRun(_runStart, _runLength) { - runStart[stackSize] = _runStart; - runLength[stackSize] = _runLength; - stackSize += 1; - } - - function mergeRuns() { - while (stackSize > 1) { - var n = stackSize - 2; - - if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) { - if (runLength[n - 1] < runLength[n + 1]) { - n--; - } - } else if (runLength[n] > runLength[n + 1]) { - break; - } - - mergeAt(n); - } - } - - function forceMergeRuns() { - while (stackSize > 1) { - var n = stackSize - 2; - - if (n > 0 && runLength[n - 1] < runLength[n + 1]) { - n--; - } - - mergeAt(n); - } - } - - function mergeAt(i) { - var start1 = runStart[i]; - var length1 = runLength[i]; - var start2 = runStart[i + 1]; - var length2 = runLength[i + 1]; - runLength[i] = length1 + length2; - - if (i === stackSize - 3) { - runStart[i + 1] = runStart[i + 2]; - runLength[i + 1] = runLength[i + 2]; - } - - stackSize--; - var k = gallopRight(array[start2], array, start1, length1, 0, compare); - start1 += k; - length1 -= k; - - if (length1 === 0) { - return; - } - - length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); - - if (length2 === 0) { - return; - } - - if (length1 <= length2) { - mergeLow(start1, length1, start2, length2); - } else { - mergeHigh(start1, length1, start2, length2); - } - } - - function mergeLow(start1, length1, start2, length2) { - var i = 0; - - for (i = 0; i < length1; i++) { - tmp[i] = array[start1 + i]; - } - - var cursor1 = 0; - var cursor2 = start2; - var dest = start1; - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - return; - } - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - array[dest + length2] = tmp[cursor1]; - return; - } - - var _minGallop = minGallop; - var count1; - var count2; - var exit; - - while (1) { - count1 = 0; - count2 = 0; - exit = false; - - do { - if (compare(array[cursor2], tmp[cursor1]) < 0) { - array[dest++] = array[cursor2++]; - count2++; - count1 = 0; - - if (--length2 === 0) { - exit = true; - break; - } - } else { - array[dest++] = tmp[cursor1++]; - count1++; - count2 = 0; - - if (--length1 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < _minGallop); - - if (exit) { - break; - } - - do { - count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); - - if (count1 !== 0) { - for (i = 0; i < count1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - - dest += count1; - cursor1 += count1; - length1 -= count1; - - if (length1 <= 1) { - exit = true; - break; - } - } - - array[dest++] = array[cursor2++]; - - if (--length2 === 0) { - exit = true; - break; - } - - count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); - - if (count2 !== 0) { - for (i = 0; i < count2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - dest += count2; - cursor2 += count2; - length2 -= count2; - - if (length2 === 0) { - exit = true; - break; - } - } - - array[dest++] = tmp[cursor1++]; - - if (--length1 === 1) { - exit = true; - break; - } - - _minGallop--; - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (_minGallop < 0) { - _minGallop = 0; - } - - _minGallop += 2; - } - - minGallop = _minGallop; - minGallop < 1 && (minGallop = 1); - - if (length1 === 1) { - for (i = 0; i < length2; i++) { - array[dest + i] = array[cursor2 + i]; - } - - array[dest + length2] = tmp[cursor1]; - } else if (length1 === 0) { - throw new Error(); - } else { - for (i = 0; i < length1; i++) { - array[dest + i] = tmp[cursor1 + i]; - } - } - } - - function mergeHigh(start1, length1, start2, length2) { - var i = 0; - - for (i = 0; i < length2; i++) { - tmp[i] = array[start2 + i]; - } - - var cursor1 = start1 + length1 - 1; - var cursor2 = length2 - 1; - var dest = start2 + length2 - 1; - var customCursor = 0; - var customDest = 0; - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - - return; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - return; - } - - var _minGallop = minGallop; - - while (true) { - var count1 = 0; - var count2 = 0; - var exit = false; - - do { - if (compare(tmp[cursor2], array[cursor1]) < 0) { - array[dest--] = array[cursor1--]; - count1++; - count2 = 0; - - if (--length1 === 0) { - exit = true; - break; - } - } else { - array[dest--] = tmp[cursor2--]; - count2++; - count1 = 0; - - if (--length2 === 1) { - exit = true; - break; - } - } - } while ((count1 | count2) < _minGallop); - - if (exit) { - break; - } - - do { - count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); - - if (count1 !== 0) { - dest -= count1; - cursor1 -= count1; - length1 -= count1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = count1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - if (length1 === 0) { - exit = true; - break; - } - } - - array[dest--] = tmp[cursor2--]; - - if (--length2 === 1) { - exit = true; - break; - } - - count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); - - if (count2 !== 0) { - dest -= count2; - cursor2 -= count2; - length2 -= count2; - customDest = dest + 1; - customCursor = cursor2 + 1; - - for (i = 0; i < count2; i++) { - array[customDest + i] = tmp[customCursor + i]; - } - - if (length2 <= 1) { - exit = true; - break; - } - } - - array[dest--] = array[cursor1--]; - - if (--length1 === 0) { - exit = true; - break; - } - - _minGallop--; - } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); - - if (exit) { - break; - } - - if (_minGallop < 0) { - _minGallop = 0; - } - - _minGallop += 2; - } - - minGallop = _minGallop; - - if (minGallop < 1) { - minGallop = 1; - } - - if (length2 === 1) { - dest -= length1; - cursor1 -= length1; - customDest = dest + 1; - customCursor = cursor1 + 1; - - for (i = length1 - 1; i >= 0; i--) { - array[customDest + i] = array[customCursor + i]; - } - - array[dest] = tmp[cursor2]; - } else if (length2 === 0) { - throw new Error(); - } else { - customCursor = dest - (length2 - 1); - - for (i = 0; i < length2; i++) { - array[customCursor + i] = tmp[i]; - } - } - } - - return { - mergeRuns: mergeRuns, - forceMergeRuns: forceMergeRuns, - pushRun: pushRun - }; - } - - function sort(array, compare, lo, hi) { - if (!lo) { - lo = 0; - } - - if (!hi) { - hi = array.length; - } - - var remaining = hi - lo; - - if (remaining < 2) { - return; - } - - var runLength = 0; - - if (remaining < DEFAULT_MIN_MERGE) { - runLength = makeAscendingRun(array, lo, hi, compare); - binaryInsertionSort(array, lo, hi, lo + runLength, compare); - return; - } - - var ts = TimSort(array, compare); - var minRun = minRunLength(remaining); - - do { - runLength = makeAscendingRun(array, lo, hi, compare); - - if (runLength < minRun) { - var force = remaining; - - if (force > minRun) { - force = minRun; - } - - binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); - runLength = force; - } - - ts.pushRun(lo, runLength); - ts.mergeRuns(); - remaining -= runLength; - lo += runLength; - } while (remaining !== 0); - - ts.forceMergeRuns(); - } - - var REDRAW_BIT = 1; - var STYLE_CHANGED_BIT = 2; - var SHAPE_CHANGED_BIT = 4; - var invalidZErrorLogged = false; - - function logInvalidZError() { - if (invalidZErrorLogged) { - return; - } - - invalidZErrorLogged = true; - console.warn('z / z2 / zlevel of displayable is invalid, which may cause unexpected errors'); - } - - function shapeCompareFunc(a, b) { - if (a.zlevel === b.zlevel) { - if (a.z === b.z) { - return a.z2 - b.z2; - } - - return a.z - b.z; - } - - return a.zlevel - b.zlevel; - } - - var Storage = function () { - function Storage() { - this._roots = []; - this._displayList = []; - this._displayListLen = 0; - this.displayableSortFunc = shapeCompareFunc; - } - - Storage.prototype.traverse = function (cb, context) { - for (var i = 0; i < this._roots.length; i++) { - this._roots[i].traverse(cb, context); - } - }; - - Storage.prototype.getDisplayList = function (update, includeIgnore) { - includeIgnore = includeIgnore || false; - var displayList = this._displayList; - - if (update || !displayList.length) { - this.updateDisplayList(includeIgnore); - } - - return displayList; - }; - - Storage.prototype.updateDisplayList = function (includeIgnore) { - this._displayListLen = 0; - var roots = this._roots; - var displayList = this._displayList; - - for (var i = 0, len = roots.length; i < len; i++) { - this._updateAndAddDisplayable(roots[i], null, includeIgnore); - } - - displayList.length = this._displayListLen; - sort(displayList, shapeCompareFunc); - }; - - Storage.prototype._updateAndAddDisplayable = function (el, clipPaths, includeIgnore) { - if (el.ignore && !includeIgnore) { - return; - } - - el.beforeUpdate(); - el.update(); - el.afterUpdate(); - var userSetClipPath = el.getClipPath(); - - if (el.ignoreClip) { - clipPaths = null; - } else if (userSetClipPath) { - if (clipPaths) { - clipPaths = clipPaths.slice(); - } else { - clipPaths = []; - } - - var currentClipPath = userSetClipPath; - var parentClipPath = el; - - while (currentClipPath) { - currentClipPath.parent = parentClipPath; - currentClipPath.updateTransform(); - clipPaths.push(currentClipPath); - parentClipPath = currentClipPath; - currentClipPath = currentClipPath.getClipPath(); - } - } - - if (el.childrenRef) { - var children = el.childrenRef(); - - for (var i = 0; i < children.length; i++) { - var child = children[i]; - - if (el.__dirty) { - child.__dirty |= REDRAW_BIT; - } - - this._updateAndAddDisplayable(child, clipPaths, includeIgnore); - } - - el.__dirty = 0; - } else { - var disp = el; - - if (clipPaths && clipPaths.length) { - disp.__clipPaths = clipPaths; - } else if (disp.__clipPaths && disp.__clipPaths.length > 0) { - disp.__clipPaths = []; - } - - if (isNaN(disp.z)) { - logInvalidZError(); - disp.z = 0; - } - - if (isNaN(disp.z2)) { - logInvalidZError(); - disp.z2 = 0; - } - - if (isNaN(disp.zlevel)) { - logInvalidZError(); - disp.zlevel = 0; - } - - this._displayList[this._displayListLen++] = disp; - } - - var decalEl = el.getDecalElement && el.getDecalElement(); - - if (decalEl) { - this._updateAndAddDisplayable(decalEl, clipPaths, includeIgnore); - } - - var textGuide = el.getTextGuideLine(); - - if (textGuide) { - this._updateAndAddDisplayable(textGuide, clipPaths, includeIgnore); - } - - var textEl = el.getTextContent(); - - if (textEl) { - this._updateAndAddDisplayable(textEl, clipPaths, includeIgnore); - } - }; - - Storage.prototype.addRoot = function (el) { - if (el.__zr && el.__zr.storage === this) { - return; - } - - this._roots.push(el); - }; - - Storage.prototype.delRoot = function (el) { - if (el instanceof Array) { - for (var i = 0, l = el.length; i < l; i++) { - this.delRoot(el[i]); - } - - return; - } - - var idx = indexOf(this._roots, el); - - if (idx >= 0) { - this._roots.splice(idx, 1); - } - }; - - Storage.prototype.delAllRoots = function () { - this._roots = []; - this._displayList = []; - this._displayListLen = 0; - return; - }; - - Storage.prototype.getRoots = function () { - return this._roots; - }; - - Storage.prototype.dispose = function () { - this._displayList = null; - this._roots = null; - }; - - return Storage; - }(); - - var requestAnimationFrame; - - requestAnimationFrame = env.hasGlobalWindow && (window.requestAnimationFrame && window.requestAnimationFrame.bind(window) || window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window) || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame) || function (func) { - return setTimeout(func, 16); - }; - - var requestAnimationFrame$1 = requestAnimationFrame; - var easingFuncs = { - linear: function (k) { - return k; - }, - quadraticIn: function (k) { - return k * k; - }, - quadraticOut: function (k) { - return k * (2 - k); - }, - quadraticInOut: function (k) { - if ((k *= 2) < 1) { - return 0.5 * k * k; - } - - return -0.5 * (--k * (k - 2) - 1); - }, - cubicIn: function (k) { - return k * k * k; - }, - cubicOut: function (k) { - return --k * k * k + 1; - }, - cubicInOut: function (k) { - if ((k *= 2) < 1) { - return 0.5 * k * k * k; - } - - return 0.5 * ((k -= 2) * k * k + 2); - }, - quarticIn: function (k) { - return k * k * k * k; - }, - quarticOut: function (k) { - return 1 - --k * k * k * k; - }, - quarticInOut: function (k) { - if ((k *= 2) < 1) { - return 0.5 * k * k * k * k; - } - - return -0.5 * ((k -= 2) * k * k * k - 2); - }, - quinticIn: function (k) { - return k * k * k * k * k; - }, - quinticOut: function (k) { - return --k * k * k * k * k + 1; - }, - quinticInOut: function (k) { - if ((k *= 2) < 1) { - return 0.5 * k * k * k * k * k; - } - - return 0.5 * ((k -= 2) * k * k * k * k + 2); - }, - sinusoidalIn: function (k) { - return 1 - Math.cos(k * Math.PI / 2); - }, - sinusoidalOut: function (k) { - return Math.sin(k * Math.PI / 2); - }, - sinusoidalInOut: function (k) { - return 0.5 * (1 - Math.cos(Math.PI * k)); - }, - exponentialIn: function (k) { - return k === 0 ? 0 : Math.pow(1024, k - 1); - }, - exponentialOut: function (k) { - return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); - }, - exponentialInOut: function (k) { - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - if ((k *= 2) < 1) { - return 0.5 * Math.pow(1024, k - 1); - } - - return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); - }, - circularIn: function (k) { - return 1 - Math.sqrt(1 - k * k); - }, - circularOut: function (k) { - return Math.sqrt(1 - --k * k); - }, - circularInOut: function (k) { - if ((k *= 2) < 1) { - return -0.5 * (Math.sqrt(1 - k * k) - 1); - } - - return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); - }, - elasticIn: function (k) { - var s; - var a = 0.1; - var p = 0.4; - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - if (!a || a < 1) { - a = 1; - s = p / 4; - } else { - s = p * Math.asin(1 / a) / (2 * Math.PI); - } - - return -(a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p)); - }, - elasticOut: function (k) { - var s; - var a = 0.1; - var p = 0.4; - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - if (!a || a < 1) { - a = 1; - s = p / 4; - } else { - s = p * Math.asin(1 / a) / (2 * Math.PI); - } - - return a * Math.pow(2, -10 * k) * Math.sin((k - s) * (2 * Math.PI) / p) + 1; - }, - elasticInOut: function (k) { - var s; - var a = 0.1; - var p = 0.4; - - if (k === 0) { - return 0; - } - - if (k === 1) { - return 1; - } - - if (!a || a < 1) { - a = 1; - s = p / 4; - } else { - s = p * Math.asin(1 / a) / (2 * Math.PI); - } - - if ((k *= 2) < 1) { - return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p)); - } - - return a * Math.pow(2, -10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; - }, - backIn: function (k) { - var s = 1.70158; - return k * k * ((s + 1) * k - s); - }, - backOut: function (k) { - var s = 1.70158; - return --k * k * ((s + 1) * k + s) + 1; - }, - backInOut: function (k) { - var s = 1.70158 * 1.525; - - if ((k *= 2) < 1) { - return 0.5 * (k * k * ((s + 1) * k - s)); - } - - return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); - }, - bounceIn: function (k) { - return 1 - easingFuncs.bounceOut(1 - k); - }, - bounceOut: function (k) { - if (k < 1 / 2.75) { - return 7.5625 * k * k; - } else if (k < 2 / 2.75) { - return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75; - } else if (k < 2.5 / 2.75) { - return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375; - } else { - return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375; - } - }, - bounceInOut: function (k) { - if (k < 0.5) { - return easingFuncs.bounceIn(k * 2) * 0.5; - } - - return easingFuncs.bounceOut(k * 2 - 1) * 0.5 + 0.5; - } - }; - var mathPow$1 = Math.pow; - var mathSqrt$3 = Math.sqrt; - var EPSILON$4 = 1e-8; - var EPSILON_NUMERIC = 1e-4; - var THREE_SQRT = mathSqrt$3(3); - var ONE_THIRD = 1 / 3; - - var _v0 = create$1(); - - var _v1 = create$1(); - - var _v2 = create$1(); - - function isAroundZero$1(val) { - return val > -EPSILON$4 && val < EPSILON$4; - } - - function isNotAroundZero$1(val) { - return val > EPSILON$4 || val < -EPSILON$4; - } - - function cubicAt(p0, p1, p2, p3, t) { - var onet = 1 - t; - return onet * onet * (onet * p0 + 3 * t * p1) + t * t * (t * p3 + 3 * onet * p2); - } - - function cubicDerivativeAt(p0, p1, p2, p3, t) { - var onet = 1 - t; - return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + (p3 - p2) * t * t); - } - - function cubicRootAt(p0, p1, p2, p3, val, roots) { - var a = p3 + 3 * (p1 - p2) - p0; - var b = 3 * (p2 - p1 * 2 + p0); - var c = 3 * (p1 - p0); - var d = p0 - val; - var A = b * b - 3 * a * c; - var B = b * c - 9 * a * d; - var C = c * c - 3 * b * d; - var n = 0; - - if (isAroundZero$1(A) && isAroundZero$1(B)) { - if (isAroundZero$1(b)) { - roots[0] = 0; - } else { - var t1 = -c / b; - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - } - } else { - var disc = B * B - 4 * A * C; - - if (isAroundZero$1(disc)) { - var K = B / A; - var t1 = -b / a + K; - var t2 = -K / 2; - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - - if (t2 >= 0 && t2 <= 1) { - roots[n++] = t2; - } - } else if (disc > 0) { - var discSqrt = mathSqrt$3(disc); - var Y1 = A * b + 1.5 * a * (-B + discSqrt); - var Y2 = A * b + 1.5 * a * (-B - discSqrt); - - if (Y1 < 0) { - Y1 = -mathPow$1(-Y1, ONE_THIRD); - } else { - Y1 = mathPow$1(Y1, ONE_THIRD); - } - - if (Y2 < 0) { - Y2 = -mathPow$1(-Y2, ONE_THIRD); - } else { - Y2 = mathPow$1(Y2, ONE_THIRD); - } - - var t1 = (-b - (Y1 + Y2)) / (3 * a); - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - } else { - var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt$3(A * A * A)); - var theta = Math.acos(T) / 3; - var ASqrt = mathSqrt$3(A); - var tmp = Math.cos(theta); - var t1 = (-b - 2 * ASqrt * tmp) / (3 * a); - var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a); - var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a); - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - - if (t2 >= 0 && t2 <= 1) { - roots[n++] = t2; - } - - if (t3 >= 0 && t3 <= 1) { - roots[n++] = t3; - } - } - } - - return n; - } - - function cubicExtrema(p0, p1, p2, p3, extrema) { - var b = 6 * p2 - 12 * p1 + 6 * p0; - var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2; - var c = 3 * p1 - 3 * p0; - var n = 0; - - if (isAroundZero$1(a)) { - if (isNotAroundZero$1(b)) { - var t1 = -c / b; - - if (t1 >= 0 && t1 <= 1) { - extrema[n++] = t1; - } - } - } else { - var disc = b * b - 4 * a * c; - - if (isAroundZero$1(disc)) { - extrema[0] = -b / (2 * a); - } else if (disc > 0) { - var discSqrt = mathSqrt$3(disc); - var t1 = (-b + discSqrt) / (2 * a); - var t2 = (-b - discSqrt) / (2 * a); - - if (t1 >= 0 && t1 <= 1) { - extrema[n++] = t1; - } - - if (t2 >= 0 && t2 <= 1) { - extrema[n++] = t2; - } - } - } - - return n; - } - - function cubicSubdivide(p0, p1, p2, p3, t, out) { - var p01 = (p1 - p0) * t + p0; - var p12 = (p2 - p1) * t + p1; - var p23 = (p3 - p2) * t + p2; - var p012 = (p12 - p01) * t + p01; - var p123 = (p23 - p12) * t + p12; - var p0123 = (p123 - p012) * t + p012; - out[0] = p0; - out[1] = p01; - out[2] = p012; - out[3] = p0123; - out[4] = p0123; - out[5] = p123; - out[6] = p23; - out[7] = p3; - } - - function cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, out) { - var t; - var interval = 0.005; - var d = Infinity; - var prev; - var next; - var d1; - var d2; - _v0[0] = x; - _v0[1] = y; - - for (var _t = 0; _t < 1; _t += 0.05) { - _v1[0] = cubicAt(x0, x1, x2, x3, _t); - _v1[1] = cubicAt(y0, y1, y2, y3, _t); - d1 = distSquare(_v0, _v1); - - if (d1 < d) { - t = _t; - d = d1; - } - } - - d = Infinity; - - for (var i = 0; i < 32; i++) { - if (interval < EPSILON_NUMERIC) { - break; - } - - prev = t - interval; - next = t + interval; - _v1[0] = cubicAt(x0, x1, x2, x3, prev); - _v1[1] = cubicAt(y0, y1, y2, y3, prev); - d1 = distSquare(_v1, _v0); - - if (prev >= 0 && d1 < d) { - t = prev; - d = d1; - } else { - _v2[0] = cubicAt(x0, x1, x2, x3, next); - _v2[1] = cubicAt(y0, y1, y2, y3, next); - d2 = distSquare(_v2, _v0); - - if (next <= 1 && d2 < d) { - t = next; - d = d2; - } else { - interval *= 0.5; - } - } - } - - if (out) { - out[0] = cubicAt(x0, x1, x2, x3, t); - out[1] = cubicAt(y0, y1, y2, y3, t); - } - - return mathSqrt$3(d); - } - - function cubicLength(x0, y0, x1, y1, x2, y2, x3, y3, iteration) { - var px = x0; - var py = y0; - var d = 0; - var step = 1 / iteration; - - for (var i = 1; i <= iteration; i++) { - var t = i * step; - var x = cubicAt(x0, x1, x2, x3, t); - var y = cubicAt(y0, y1, y2, y3, t); - var dx = x - px; - var dy = y - py; - d += Math.sqrt(dx * dx + dy * dy); - px = x; - py = y; - } - - return d; - } - - function quadraticAt(p0, p1, p2, t) { - var onet = 1 - t; - return onet * (onet * p0 + 2 * t * p1) + t * t * p2; - } - - function quadraticDerivativeAt(p0, p1, p2, t) { - return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1)); - } - - function quadraticRootAt(p0, p1, p2, val, roots) { - var a = p0 - 2 * p1 + p2; - var b = 2 * (p1 - p0); - var c = p0 - val; - var n = 0; - - if (isAroundZero$1(a)) { - if (isNotAroundZero$1(b)) { - var t1 = -c / b; - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - } - } else { - var disc = b * b - 4 * a * c; - - if (isAroundZero$1(disc)) { - var t1 = -b / (2 * a); - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - } else if (disc > 0) { - var discSqrt = mathSqrt$3(disc); - var t1 = (-b + discSqrt) / (2 * a); - var t2 = (-b - discSqrt) / (2 * a); - - if (t1 >= 0 && t1 <= 1) { - roots[n++] = t1; - } - - if (t2 >= 0 && t2 <= 1) { - roots[n++] = t2; - } - } - } - - return n; - } - - function quadraticExtremum(p0, p1, p2) { - var divider = p0 + p2 - 2 * p1; - - if (divider === 0) { - return 0.5; - } else { - return (p0 - p1) / divider; - } - } - - function quadraticSubdivide(p0, p1, p2, t, out) { - var p01 = (p1 - p0) * t + p0; - var p12 = (p2 - p1) * t + p1; - var p012 = (p12 - p01) * t + p01; - out[0] = p0; - out[1] = p01; - out[2] = p012; - out[3] = p012; - out[4] = p12; - out[5] = p2; - } - - function quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, out) { - var t; - var interval = 0.005; - var d = Infinity; - _v0[0] = x; - _v0[1] = y; - - for (var _t = 0; _t < 1; _t += 0.05) { - _v1[0] = quadraticAt(x0, x1, x2, _t); - _v1[1] = quadraticAt(y0, y1, y2, _t); - var d1 = distSquare(_v0, _v1); - - if (d1 < d) { - t = _t; - d = d1; - } - } - - d = Infinity; - - for (var i = 0; i < 32; i++) { - if (interval < EPSILON_NUMERIC) { - break; - } - - var prev = t - interval; - var next = t + interval; - _v1[0] = quadraticAt(x0, x1, x2, prev); - _v1[1] = quadraticAt(y0, y1, y2, prev); - var d1 = distSquare(_v1, _v0); - - if (prev >= 0 && d1 < d) { - t = prev; - d = d1; - } else { - _v2[0] = quadraticAt(x0, x1, x2, next); - _v2[1] = quadraticAt(y0, y1, y2, next); - var d2 = distSquare(_v2, _v0); - - if (next <= 1 && d2 < d) { - t = next; - d = d2; - } else { - interval *= 0.5; - } - } - } - - if (out) { - out[0] = quadraticAt(x0, x1, x2, t); - out[1] = quadraticAt(y0, y1, y2, t); - } - - return mathSqrt$3(d); - } - - function quadraticLength(x0, y0, x1, y1, x2, y2, iteration) { - var px = x0; - var py = y0; - var d = 0; - var step = 1 / iteration; - - for (var i = 1; i <= iteration; i++) { - var t = i * step; - var x = quadraticAt(x0, x1, x2, t); - var y = quadraticAt(y0, y1, y2, t); - var dx = x - px; - var dy = y - py; - d += Math.sqrt(dx * dx + dy * dy); - px = x; - py = y; - } - - return d; - } - - var regexp = /cubic-bezier\(([0-9,\.e ]+)\)/; - - function createCubicEasingFunc(cubicEasingStr) { - var cubic = cubicEasingStr && regexp.exec(cubicEasingStr); - - if (cubic) { - var points = cubic[1].split(','); - var a_1 = +trim(points[0]); - var b_1 = +trim(points[1]); - var c_1 = +trim(points[2]); - var d_1 = +trim(points[3]); - - if (isNaN(a_1 + b_1 + c_1 + d_1)) { - return; - } - - var roots_1 = []; - return function (p) { - return p <= 0 ? 0 : p >= 1 ? 1 : cubicRootAt(0, a_1, c_1, 1, p, roots_1) && cubicAt(0, b_1, d_1, 1, roots_1[0]); - }; - } - } - - var Clip = function () { - function Clip(opts) { - this._inited = false; - this._startTime = 0; - this._pausedTime = 0; - this._paused = false; - this._life = opts.life || 1000; - this._delay = opts.delay || 0; - this.loop = opts.loop || false; - this.onframe = opts.onframe || noop; - this.ondestroy = opts.ondestroy || noop; - this.onrestart = opts.onrestart || noop; - opts.easing && this.setEasing(opts.easing); - } - - Clip.prototype.step = function (globalTime, deltaTime) { - if (!this._inited) { - this._startTime = globalTime + this._delay; - this._inited = true; - } - - if (this._paused) { - this._pausedTime += deltaTime; - return; - } - - var life = this._life; - var elapsedTime = globalTime - this._startTime - this._pausedTime; - var percent = elapsedTime / life; - - if (percent < 0) { - percent = 0; - } - - percent = Math.min(percent, 1); - var easingFunc = this.easingFunc; - var schedule = easingFunc ? easingFunc(percent) : percent; - this.onframe(schedule); - - if (percent === 1) { - if (this.loop) { - var remainder = elapsedTime % life; - this._startTime = globalTime - remainder; - this._pausedTime = 0; - this.onrestart(); - } else { - return true; - } - } - - return false; - }; - - Clip.prototype.pause = function () { - this._paused = true; - }; - - Clip.prototype.resume = function () { - this._paused = false; - }; - - Clip.prototype.setEasing = function (easing) { - this.easing = easing; - this.easingFunc = isFunction(easing) ? easing : easingFuncs[easing] || createCubicEasingFunc(easing); - }; - - return Clip; - }(); - - var Entry = function () { - function Entry(val) { - this.value = val; - } - - return Entry; - }(); - - var LinkedList = function () { - function LinkedList() { - this._len = 0; - } - - LinkedList.prototype.insert = function (val) { - var entry = new Entry(val); - this.insertEntry(entry); - return entry; - }; - - LinkedList.prototype.insertEntry = function (entry) { - if (!this.head) { - this.head = this.tail = entry; - } else { - this.tail.next = entry; - entry.prev = this.tail; - entry.next = null; - this.tail = entry; - } - - this._len++; - }; - - LinkedList.prototype.remove = function (entry) { - var prev = entry.prev; - var next = entry.next; - - if (prev) { - prev.next = next; - } else { - this.head = next; - } - - if (next) { - next.prev = prev; - } else { - this.tail = prev; - } - - entry.next = entry.prev = null; - this._len--; - }; - - LinkedList.prototype.len = function () { - return this._len; - }; - - LinkedList.prototype.clear = function () { - this.head = this.tail = null; - this._len = 0; - }; - - return LinkedList; - }(); - - var LRU = function () { - function LRU(maxSize) { - this._list = new LinkedList(); - this._maxSize = 10; - this._map = {}; - this._maxSize = maxSize; - } - - LRU.prototype.put = function (key, value) { - var list = this._list; - var map = this._map; - var removed = null; - - if (map[key] == null) { - var len = list.len(); - var entry = this._lastRemovedEntry; - - if (len >= this._maxSize && len > 0) { - var leastUsedEntry = list.head; - list.remove(leastUsedEntry); - delete map[leastUsedEntry.key]; - removed = leastUsedEntry.value; - this._lastRemovedEntry = leastUsedEntry; - } - - if (entry) { - entry.value = value; - } else { - entry = new Entry(value); - } - - entry.key = key; - list.insertEntry(entry); - map[key] = entry; - } - - return removed; - }; - - LRU.prototype.get = function (key) { - var entry = this._map[key]; - var list = this._list; - - if (entry != null) { - if (entry !== list.tail) { - list.remove(entry); - list.insertEntry(entry); - } - - return entry.value; - } - }; - - LRU.prototype.clear = function () { - this._list.clear(); - - this._map = {}; - }; - - LRU.prototype.len = function () { - return this._list.len(); - }; - - return LRU; - }(); - - var kCSSColorTable = { - 'transparent': [0, 0, 0, 0], - 'aliceblue': [240, 248, 255, 1], - 'antiquewhite': [250, 235, 215, 1], - 'aqua': [0, 255, 255, 1], - 'aquamarine': [127, 255, 212, 1], - 'azure': [240, 255, 255, 1], - 'beige': [245, 245, 220, 1], - 'bisque': [255, 228, 196, 1], - 'black': [0, 0, 0, 1], - 'blanchedalmond': [255, 235, 205, 1], - 'blue': [0, 0, 255, 1], - 'blueviolet': [138, 43, 226, 1], - 'brown': [165, 42, 42, 1], - 'burlywood': [222, 184, 135, 1], - 'cadetblue': [95, 158, 160, 1], - 'chartreuse': [127, 255, 0, 1], - 'chocolate': [210, 105, 30, 1], - 'coral': [255, 127, 80, 1], - 'cornflowerblue': [100, 149, 237, 1], - 'cornsilk': [255, 248, 220, 1], - 'crimson': [220, 20, 60, 1], - 'cyan': [0, 255, 255, 1], - 'darkblue': [0, 0, 139, 1], - 'darkcyan': [0, 139, 139, 1], - 'darkgoldenrod': [184, 134, 11, 1], - 'darkgray': [169, 169, 169, 1], - 'darkgreen': [0, 100, 0, 1], - 'darkgrey': [169, 169, 169, 1], - 'darkkhaki': [189, 183, 107, 1], - 'darkmagenta': [139, 0, 139, 1], - 'darkolivegreen': [85, 107, 47, 1], - 'darkorange': [255, 140, 0, 1], - 'darkorchid': [153, 50, 204, 1], - 'darkred': [139, 0, 0, 1], - 'darksalmon': [233, 150, 122, 1], - 'darkseagreen': [143, 188, 143, 1], - 'darkslateblue': [72, 61, 139, 1], - 'darkslategray': [47, 79, 79, 1], - 'darkslategrey': [47, 79, 79, 1], - 'darkturquoise': [0, 206, 209, 1], - 'darkviolet': [148, 0, 211, 1], - 'deeppink': [255, 20, 147, 1], - 'deepskyblue': [0, 191, 255, 1], - 'dimgray': [105, 105, 105, 1], - 'dimgrey': [105, 105, 105, 1], - 'dodgerblue': [30, 144, 255, 1], - 'firebrick': [178, 34, 34, 1], - 'floralwhite': [255, 250, 240, 1], - 'forestgreen': [34, 139, 34, 1], - 'fuchsia': [255, 0, 255, 1], - 'gainsboro': [220, 220, 220, 1], - 'ghostwhite': [248, 248, 255, 1], - 'gold': [255, 215, 0, 1], - 'goldenrod': [218, 165, 32, 1], - 'gray': [128, 128, 128, 1], - 'green': [0, 128, 0, 1], - 'greenyellow': [173, 255, 47, 1], - 'grey': [128, 128, 128, 1], - 'honeydew': [240, 255, 240, 1], - 'hotpink': [255, 105, 180, 1], - 'indianred': [205, 92, 92, 1], - 'indigo': [75, 0, 130, 1], - 'ivory': [255, 255, 240, 1], - 'khaki': [240, 230, 140, 1], - 'lavender': [230, 230, 250, 1], - 'lavenderblush': [255, 240, 245, 1], - 'lawngreen': [124, 252, 0, 1], - 'lemonchiffon': [255, 250, 205, 1], - 'lightblue': [173, 216, 230, 1], - 'lightcoral': [240, 128, 128, 1], - 'lightcyan': [224, 255, 255, 1], - 'lightgoldenrodyellow': [250, 250, 210, 1], - 'lightgray': [211, 211, 211, 1], - 'lightgreen': [144, 238, 144, 1], - 'lightgrey': [211, 211, 211, 1], - 'lightpink': [255, 182, 193, 1], - 'lightsalmon': [255, 160, 122, 1], - 'lightseagreen': [32, 178, 170, 1], - 'lightskyblue': [135, 206, 250, 1], - 'lightslategray': [119, 136, 153, 1], - 'lightslategrey': [119, 136, 153, 1], - 'lightsteelblue': [176, 196, 222, 1], - 'lightyellow': [255, 255, 224, 1], - 'lime': [0, 255, 0, 1], - 'limegreen': [50, 205, 50, 1], - 'linen': [250, 240, 230, 1], - 'magenta': [255, 0, 255, 1], - 'maroon': [128, 0, 0, 1], - 'mediumaquamarine': [102, 205, 170, 1], - 'mediumblue': [0, 0, 205, 1], - 'mediumorchid': [186, 85, 211, 1], - 'mediumpurple': [147, 112, 219, 1], - 'mediumseagreen': [60, 179, 113, 1], - 'mediumslateblue': [123, 104, 238, 1], - 'mediumspringgreen': [0, 250, 154, 1], - 'mediumturquoise': [72, 209, 204, 1], - 'mediumvioletred': [199, 21, 133, 1], - 'midnightblue': [25, 25, 112, 1], - 'mintcream': [245, 255, 250, 1], - 'mistyrose': [255, 228, 225, 1], - 'moccasin': [255, 228, 181, 1], - 'navajowhite': [255, 222, 173, 1], - 'navy': [0, 0, 128, 1], - 'oldlace': [253, 245, 230, 1], - 'olive': [128, 128, 0, 1], - 'olivedrab': [107, 142, 35, 1], - 'orange': [255, 165, 0, 1], - 'orangered': [255, 69, 0, 1], - 'orchid': [218, 112, 214, 1], - 'palegoldenrod': [238, 232, 170, 1], - 'palegreen': [152, 251, 152, 1], - 'paleturquoise': [175, 238, 238, 1], - 'palevioletred': [219, 112, 147, 1], - 'papayawhip': [255, 239, 213, 1], - 'peachpuff': [255, 218, 185, 1], - 'peru': [205, 133, 63, 1], - 'pink': [255, 192, 203, 1], - 'plum': [221, 160, 221, 1], - 'powderblue': [176, 224, 230, 1], - 'purple': [128, 0, 128, 1], - 'red': [255, 0, 0, 1], - 'rosybrown': [188, 143, 143, 1], - 'royalblue': [65, 105, 225, 1], - 'saddlebrown': [139, 69, 19, 1], - 'salmon': [250, 128, 114, 1], - 'sandybrown': [244, 164, 96, 1], - 'seagreen': [46, 139, 87, 1], - 'seashell': [255, 245, 238, 1], - 'sienna': [160, 82, 45, 1], - 'silver': [192, 192, 192, 1], - 'skyblue': [135, 206, 235, 1], - 'slateblue': [106, 90, 205, 1], - 'slategray': [112, 128, 144, 1], - 'slategrey': [112, 128, 144, 1], - 'snow': [255, 250, 250, 1], - 'springgreen': [0, 255, 127, 1], - 'steelblue': [70, 130, 180, 1], - 'tan': [210, 180, 140, 1], - 'teal': [0, 128, 128, 1], - 'thistle': [216, 191, 216, 1], - 'tomato': [255, 99, 71, 1], - 'turquoise': [64, 224, 208, 1], - 'violet': [238, 130, 238, 1], - 'wheat': [245, 222, 179, 1], - 'white': [255, 255, 255, 1], - 'whitesmoke': [245, 245, 245, 1], - 'yellow': [255, 255, 0, 1], - 'yellowgreen': [154, 205, 50, 1] - }; - - function clampCssByte(i) { - i = Math.round(i); - return i < 0 ? 0 : i > 255 ? 255 : i; - } - - function clampCssAngle(i) { - i = Math.round(i); - return i < 0 ? 0 : i > 360 ? 360 : i; - } - - function clampCssFloat(f) { - return f < 0 ? 0 : f > 1 ? 1 : f; - } - - function parseCssInt(val) { - var str = val; - - if (str.length && str.charAt(str.length - 1) === '%') { - return clampCssByte(parseFloat(str) / 100 * 255); - } - - return clampCssByte(parseInt(str, 10)); - } - - function parseCssFloat(val) { - var str = val; - - if (str.length && str.charAt(str.length - 1) === '%') { - return clampCssFloat(parseFloat(str) / 100); - } - - return clampCssFloat(parseFloat(str)); - } - - function cssHueToRgb(m1, m2, h) { - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - - if (h * 6 < 1) { - return m1 + (m2 - m1) * h * 6; - } - - if (h * 2 < 1) { - return m2; - } - - if (h * 3 < 2) { - return m1 + (m2 - m1) * (2 / 3 - h) * 6; - } - - return m1; - } - - function lerpNumber(a, b, p) { - return a + (b - a) * p; - } - - function setRgba(out, r, g, b, a) { - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = a; - return out; - } - - function copyRgba(out, a) { - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - return out; - } - - var colorCache = new LRU(20); - var lastRemovedArr = null; - - function putToCache(colorStr, rgbaArr) { - if (lastRemovedArr) { - copyRgba(lastRemovedArr, rgbaArr); - } - - lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || rgbaArr.slice()); - } - - function parse(colorStr, rgbaArr) { - if (!colorStr) { - return; - } - - rgbaArr = rgbaArr || []; - var cached = colorCache.get(colorStr); - - if (cached) { - return copyRgba(rgbaArr, cached); - } - - colorStr = colorStr + ''; - var str = colorStr.replace(/ /g, '').toLowerCase(); - - if (str in kCSSColorTable) { - copyRgba(rgbaArr, kCSSColorTable[str]); - putToCache(colorStr, rgbaArr); - return rgbaArr; - } - - var strLen = str.length; - - if (str.charAt(0) === '#') { - if (strLen === 4 || strLen === 5) { - var iv = parseInt(str.slice(1, 4), 16); - - if (!(iv >= 0 && iv <= 0xfff)) { - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - setRgba(rgbaArr, (iv & 0xf00) >> 4 | (iv & 0xf00) >> 8, iv & 0xf0 | (iv & 0xf0) >> 4, iv & 0xf | (iv & 0xf) << 4, strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1); - putToCache(colorStr, rgbaArr); - return rgbaArr; - } else if (strLen === 7 || strLen === 9) { - var iv = parseInt(str.slice(1, 7), 16); - - if (!(iv >= 0 && iv <= 0xffffff)) { - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1); - putToCache(colorStr, rgbaArr); - return rgbaArr; - } - - return; - } - - var op = str.indexOf('('); - var ep = str.indexOf(')'); - - if (op !== -1 && ep + 1 === strLen) { - var fname = str.substr(0, op); - var params = str.substr(op + 1, ep - (op + 1)).split(','); - var alpha = 1; - - switch (fname) { - case 'rgba': - if (params.length !== 4) { - return params.length === 3 ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1) : setRgba(rgbaArr, 0, 0, 0, 1); - } - - alpha = parseCssFloat(params.pop()); - - case 'rgb': - if (params.length >= 3) { - setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), params.length === 3 ? alpha : parseCssFloat(params[3])); - putToCache(colorStr, rgbaArr); - return rgbaArr; - } else { - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - case 'hsla': - if (params.length !== 4) { - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - params[3] = parseCssFloat(params[3]); - hsla2rgba(params, rgbaArr); - putToCache(colorStr, rgbaArr); - return rgbaArr; - - case 'hsl': - if (params.length !== 3) { - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - hsla2rgba(params, rgbaArr); - putToCache(colorStr, rgbaArr); - return rgbaArr; - - default: - return; - } - } - - setRgba(rgbaArr, 0, 0, 0, 1); - return; - } - - function hsla2rgba(hsla, rgba) { - var h = (parseFloat(hsla[0]) % 360 + 360) % 360 / 360; - var s = parseCssFloat(hsla[1]); - var l = parseCssFloat(hsla[2]); - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - rgba = rgba || []; - setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1); - - if (hsla.length === 4) { - rgba[3] = hsla[3]; - } - - return rgba; - } - - function rgba2hsla(rgba) { - if (!rgba) { - return; - } - - var R = rgba[0] / 255; - var G = rgba[1] / 255; - var B = rgba[2] / 255; - var vMin = Math.min(R, G, B); - var vMax = Math.max(R, G, B); - var delta = vMax - vMin; - var L = (vMax + vMin) / 2; - var H; - var S; - - if (delta === 0) { - H = 0; - S = 0; - } else { - if (L < 0.5) { - S = delta / (vMax + vMin); - } else { - S = delta / (2 - vMax - vMin); - } - - var deltaR = ((vMax - R) / 6 + delta / 2) / delta; - var deltaG = ((vMax - G) / 6 + delta / 2) / delta; - var deltaB = ((vMax - B) / 6 + delta / 2) / delta; - - if (R === vMax) { - H = deltaB - deltaG; - } else if (G === vMax) { - H = 1 / 3 + deltaR - deltaB; - } else if (B === vMax) { - H = 2 / 3 + deltaG - deltaR; - } - - if (H < 0) { - H += 1; - } - - if (H > 1) { - H -= 1; - } - } - - var hsla = [H * 360, S, L]; - - if (rgba[3] != null) { - hsla.push(rgba[3]); - } - - return hsla; - } - - function lift(color, level) { - var colorArr = parse(color); - - if (colorArr) { - for (var i = 0; i < 3; i++) { - if (level < 0) { - colorArr[i] = colorArr[i] * (1 - level) | 0; - } else { - colorArr[i] = (255 - colorArr[i]) * level + colorArr[i] | 0; - } - - if (colorArr[i] > 255) { - colorArr[i] = 255; - } else if (colorArr[i] < 0) { - colorArr[i] = 0; - } - } - - return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); - } - } - - function toHex(color) { - var colorArr = parse(color); - - if (colorArr) { - return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + +colorArr[2]).toString(16).slice(1); - } - } - - function fastLerp(normalizedValue, colors, out) { - if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { - return; - } - - out = out || []; - var value = normalizedValue * (colors.length - 1); - var leftIndex = Math.floor(value); - var rightIndex = Math.ceil(value); - var leftColor = colors[leftIndex]; - var rightColor = colors[rightIndex]; - var dv = value - leftIndex; - out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); - out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); - out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); - out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); - return out; - } - - var fastMapToColor = fastLerp; - - function lerp(normalizedValue, colors, fullOutput) { - if (!(colors && colors.length) || !(normalizedValue >= 0 && normalizedValue <= 1)) { - return; - } - - var value = normalizedValue * (colors.length - 1); - var leftIndex = Math.floor(value); - var rightIndex = Math.ceil(value); - var leftColor = parse(colors[leftIndex]); - var rightColor = parse(colors[rightIndex]); - var dv = value - leftIndex; - var color = stringify([clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv))], 'rgba'); - return fullOutput ? { - color: color, - leftIndex: leftIndex, - rightIndex: rightIndex, - value: value - } : color; - } - - var mapToColor = lerp; - - function modifyHSL(color, h, s, l) { - var colorArr = parse(color); - - if (color) { - colorArr = rgba2hsla(colorArr); - h != null && (colorArr[0] = clampCssAngle(h)); - s != null && (colorArr[1] = parseCssFloat(s)); - l != null && (colorArr[2] = parseCssFloat(l)); - return stringify(hsla2rgba(colorArr), 'rgba'); - } - } - - function modifyAlpha(color, alpha) { - var colorArr = parse(color); - - if (colorArr && alpha != null) { - colorArr[3] = clampCssFloat(alpha); - return stringify(colorArr, 'rgba'); - } - } - - function stringify(arrColor, type) { - if (!arrColor || !arrColor.length) { - return; - } - - var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; - - if (type === 'rgba' || type === 'hsva' || type === 'hsla') { - colorStr += ',' + arrColor[3]; - } - - return type + '(' + colorStr + ')'; - } - - function lum(color, backgroundLum) { - var arr = parse(color); - return arr ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255 + (1 - arr[3]) * backgroundLum : 0; - } - - function random() { - return stringify([Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255)], 'rgb'); - } - - var liftedColorCache = new LRU(100); - - function liftColor(color) { - if (isString(color)) { - var liftedColor = liftedColorCache.get(color); - - if (!liftedColor) { - liftedColor = lift(color, -0.1); - liftedColorCache.put(color, liftedColor); - } - - return liftedColor; - } else if (isGradientObject(color)) { - var ret = extend({}, color); - ret.colorStops = map$1(color.colorStops, function (stop) { - return { - offset: stop.offset, - color: lift(stop.color, -0.1) - }; - }); - return ret; - } - - return color; - } - - var color = /*#__PURE__*/Object.freeze({ - __proto__: null, - fastLerp: fastLerp, - fastMapToColor: fastMapToColor, - lerp: lerp, - lift: lift, - liftColor: liftColor, - lum: lum, - mapToColor: mapToColor, - modifyAlpha: modifyAlpha, - modifyHSL: modifyHSL, - parse: parse, - random: random, - stringify: stringify, - toHex: toHex - }); - var mathRound$1 = Math.round; - - function normalizeColor(color) { - var opacity; - - if (!color || color === 'transparent') { - color = 'none'; - } else if (typeof color === 'string' && color.indexOf('rgba') > -1) { - var arr = parse(color); - - if (arr) { - color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')'; - opacity = arr[3]; - } - } - - return { - color: color, - opacity: opacity == null ? 1 : opacity - }; - } - - var EPSILON$3 = 1e-4; - - function isAroundZero(transform) { - return transform < EPSILON$3 && transform > -EPSILON$3; - } - - function round3(transform) { - return mathRound$1(transform * 1e3) / 1e3; - } - - function round4(transform) { - return mathRound$1(transform * 1e4) / 1e4; - } - - function getMatrixStr(m) { - return 'matrix(' + round3(m[0]) + ',' + round3(m[1]) + ',' + round3(m[2]) + ',' + round3(m[3]) + ',' + round4(m[4]) + ',' + round4(m[5]) + ')'; - } - - var TEXT_ALIGN_TO_ANCHOR = { - left: 'start', - right: 'end', - center: 'middle', - middle: 'middle' - }; - - function adjustTextY$1(y, lineHeight, textBaseline) { - if (textBaseline === 'top') { - y += lineHeight / 2; - } else if (textBaseline === 'bottom') { - y -= lineHeight / 2; - } - - return y; - } - - function hasShadow(style) { - return style && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); - } - - function getShadowKey(displayable) { - var style = displayable.style; - var globalScale = displayable.getGlobalScale(); - return [style.shadowColor, (style.shadowBlur || 0).toFixed(2), (style.shadowOffsetX || 0).toFixed(2), (style.shadowOffsetY || 0).toFixed(2), globalScale[0], globalScale[1]].join(','); - } - - function isImagePattern(val) { - return val && !!val.image; - } - - function isSVGPattern(val) { - return val && !!val.svgElement; - } - - function isPattern(val) { - return isImagePattern(val) || isSVGPattern(val); - } - - function isLinearGradient(val) { - return val.type === 'linear'; - } - - function isRadialGradient(val) { - return val.type === 'radial'; - } - - function isGradient(val) { - return val && (val.type === 'linear' || val.type === 'radial'); - } - - function getIdURL(id) { - return "url(#" + id + ")"; - } - - function getPathPrecision(el) { - var scale = el.getGlobalScale(); - var size = Math.max(scale[0], scale[1]); - return Math.max(Math.ceil(Math.log(size) / Math.log(10)), 1); - } - - function getSRTTransformString(transform) { - var x = transform.x || 0; - var y = transform.y || 0; - var rotation = (transform.rotation || 0) * RADIAN_TO_DEGREE; - var scaleX = retrieve2(transform.scaleX, 1); - var scaleY = retrieve2(transform.scaleY, 1); - var skewX = transform.skewX || 0; - var skewY = transform.skewY || 0; - var res = []; - - if (x || y) { - res.push("translate(" + x + "px," + y + "px)"); - } - - if (rotation) { - res.push("rotate(" + rotation + ")"); - } - - if (scaleX !== 1 || scaleY !== 1) { - res.push("scale(" + scaleX + "," + scaleY + ")"); - } - - if (skewX || skewY) { - res.push("skew(" + mathRound$1(skewX * RADIAN_TO_DEGREE) + "deg, " + mathRound$1(skewY * RADIAN_TO_DEGREE) + "deg)"); - } - - return res.join(' '); - } - - var encodeBase64 = function () { - if (env.hasGlobalWindow && isFunction(window.btoa)) { - return function (str) { - return window.btoa(unescape(encodeURIComponent(str))); - }; - } - - if (typeof Buffer !== 'undefined') { - return function (str) { - return Buffer.from(str).toString('base64'); - }; - } - - return function (str) { - { - logError('Base64 isn\'t natively supported in the current environment.'); - } - return null; - }; - }(); - - var arraySlice = Array.prototype.slice; - - function interpolateNumber$1(p0, p1, percent) { - return (p1 - p0) * percent + p0; - } - - function interpolate1DArray(out, p0, p1, percent) { - var len = p0.length; - - for (var i = 0; i < len; i++) { - out[i] = interpolateNumber$1(p0[i], p1[i], percent); - } - - return out; - } - - function interpolate2DArray(out, p0, p1, percent) { - var len = p0.length; - var len2 = len && p0[0].length; - - for (var i = 0; i < len; i++) { - if (!out[i]) { - out[i] = []; - } - - for (var j = 0; j < len2; j++) { - out[i][j] = interpolateNumber$1(p0[i][j], p1[i][j], percent); - } - } - - return out; - } - - function add1DArray(out, p0, p1, sign) { - var len = p0.length; - - for (var i = 0; i < len; i++) { - out[i] = p0[i] + p1[i] * sign; - } - - return out; - } - - function add2DArray(out, p0, p1, sign) { - var len = p0.length; - var len2 = len && p0[0].length; - - for (var i = 0; i < len; i++) { - if (!out[i]) { - out[i] = []; - } - - for (var j = 0; j < len2; j++) { - out[i][j] = p0[i][j] + p1[i][j] * sign; - } - } - - return out; - } - - function fillColorStops(val0, val1) { - var len0 = val0.length; - var len1 = val1.length; - var shorterArr = len0 > len1 ? val1 : val0; - var shorterLen = Math.min(len0, len1); - var last = shorterArr[shorterLen - 1] || { - color: [0, 0, 0, 0], - offset: 0 - }; - - for (var i = shorterLen; i < Math.max(len0, len1); i++) { - shorterArr.push({ - offset: last.offset, - color: last.color.slice() - }); - } - } - - function fillArray(val0, val1, arrDim) { - var arr0 = val0; - var arr1 = val1; - - if (!arr0.push || !arr1.push) { - return; - } - - var arr0Len = arr0.length; - var arr1Len = arr1.length; - - if (arr0Len !== arr1Len) { - var isPreviousLarger = arr0Len > arr1Len; - - if (isPreviousLarger) { - arr0.length = arr1Len; - } else { - for (var i = arr0Len; i < arr1Len; i++) { - arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])); - } - } - } - - var len2 = arr0[0] && arr0[0].length; - - for (var i = 0; i < arr0.length; i++) { - if (arrDim === 1) { - if (isNaN(arr0[i])) { - arr0[i] = arr1[i]; - } - } else { - for (var j = 0; j < len2; j++) { - if (isNaN(arr0[i][j])) { - arr0[i][j] = arr1[i][j]; - } - } - } - } - } - - function cloneValue(value) { - if (isArrayLike(value)) { - var len = value.length; - - if (isArrayLike(value[0])) { - var ret = []; - - for (var i = 0; i < len; i++) { - ret.push(arraySlice.call(value[i])); - } - - return ret; - } - - return arraySlice.call(value); - } - - return value; - } - - function rgba2String(rgba) { - rgba[0] = Math.floor(rgba[0]) || 0; - rgba[1] = Math.floor(rgba[1]) || 0; - rgba[2] = Math.floor(rgba[2]) || 0; - rgba[3] = rgba[3] == null ? 1 : rgba[3]; - return 'rgba(' + rgba.join(',') + ')'; - } - - function guessArrayDim(value) { - return isArrayLike(value && value[0]) ? 2 : 1; - } - - var VALUE_TYPE_NUMBER = 0; - var VALUE_TYPE_1D_ARRAY = 1; - var VALUE_TYPE_2D_ARRAY = 2; - var VALUE_TYPE_COLOR = 3; - var VALUE_TYPE_LINEAR_GRADIENT = 4; - var VALUE_TYPE_RADIAL_GRADIENT = 5; - var VALUE_TYPE_UNKOWN = 6; - - function isGradientValueType(valType) { - return valType === VALUE_TYPE_LINEAR_GRADIENT || valType === VALUE_TYPE_RADIAL_GRADIENT; - } - - function isArrayValueType(valType) { - return valType === VALUE_TYPE_1D_ARRAY || valType === VALUE_TYPE_2D_ARRAY; - } - - var tmpRgba = [0, 0, 0, 0]; - - var Track = function () { - function Track(propName) { - this.keyframes = []; - this.discrete = false; - this._invalid = false; - this._needsSort = false; - this._lastFr = 0; - this._lastFrP = 0; - this.propName = propName; - } - - Track.prototype.isFinished = function () { - return this._finished; - }; - - Track.prototype.setFinished = function () { - this._finished = true; - - if (this._additiveTrack) { - this._additiveTrack.setFinished(); - } - }; - - Track.prototype.needsAnimate = function () { - return this.keyframes.length >= 1; - }; - - Track.prototype.getAdditiveTrack = function () { - return this._additiveTrack; - }; - - Track.prototype.addKeyframe = function (time, rawValue, easing) { - this._needsSort = true; - var keyframes = this.keyframes; - var len = keyframes.length; - var discrete = false; - var valType = VALUE_TYPE_UNKOWN; - var value = rawValue; - - if (isArrayLike(rawValue)) { - var arrayDim = guessArrayDim(rawValue); - valType = arrayDim; - - if (arrayDim === 1 && !isNumber(rawValue[0]) || arrayDim === 2 && !isNumber(rawValue[0][0])) { - discrete = true; - } - } else { - if (isNumber(rawValue) && !eqNaN(rawValue)) { - valType = VALUE_TYPE_NUMBER; - } else if (isString(rawValue)) { - if (!isNaN(+rawValue)) { - valType = VALUE_TYPE_NUMBER; - } else { - var colorArray = parse(rawValue); - - if (colorArray) { - value = colorArray; - valType = VALUE_TYPE_COLOR; - } - } - } else if (isGradientObject(rawValue)) { - var parsedGradient = extend({}, value); - parsedGradient.colorStops = map$1(rawValue.colorStops, function (colorStop) { - return { - offset: colorStop.offset, - color: parse(colorStop.color) - }; - }); - - if (isLinearGradient(rawValue)) { - valType = VALUE_TYPE_LINEAR_GRADIENT; - } else if (isRadialGradient(rawValue)) { - valType = VALUE_TYPE_RADIAL_GRADIENT; - } - - value = parsedGradient; - } - } - - if (len === 0) { - this.valType = valType; - } else if (valType !== this.valType || valType === VALUE_TYPE_UNKOWN) { - discrete = true; - } - - this.discrete = this.discrete || discrete; - var kf = { - time: time, - value: value, - rawValue: rawValue, - percent: 0 - }; - - if (easing) { - kf.easing = easing; - kf.easingFunc = isFunction(easing) ? easing : easingFuncs[easing] || createCubicEasingFunc(easing); - } - - keyframes.push(kf); - return kf; - }; - - Track.prototype.prepare = function (maxTime, additiveTrack) { - var kfs = this.keyframes; - - if (this._needsSort) { - kfs.sort(function (a, b) { - return a.time - b.time; - }); - } - - var valType = this.valType; - var kfsLen = kfs.length; - var lastKf = kfs[kfsLen - 1]; - var isDiscrete = this.discrete; - var isArr = isArrayValueType(valType); - var isGradient = isGradientValueType(valType); - - for (var i = 0; i < kfsLen; i++) { - var kf = kfs[i]; - var value = kf.value; - var lastValue = lastKf.value; - kf.percent = kf.time / maxTime; - - if (!isDiscrete) { - if (isArr && i !== kfsLen - 1) { - fillArray(value, lastValue, valType); - } else if (isGradient) { - fillColorStops(value.colorStops, lastValue.colorStops); - } - } - } - - if (!isDiscrete && valType !== VALUE_TYPE_RADIAL_GRADIENT && additiveTrack && this.needsAnimate() && additiveTrack.needsAnimate() && valType === additiveTrack.valType && !additiveTrack._finished) { - this._additiveTrack = additiveTrack; - var startValue = kfs[0].value; - - for (var i = 0; i < kfsLen; i++) { - if (valType === VALUE_TYPE_NUMBER) { - kfs[i].additiveValue = kfs[i].value - startValue; - } else if (valType === VALUE_TYPE_COLOR) { - kfs[i].additiveValue = add1DArray([], kfs[i].value, startValue, -1); - } else if (isArrayValueType(valType)) { - kfs[i].additiveValue = valType === VALUE_TYPE_1D_ARRAY ? add1DArray([], kfs[i].value, startValue, -1) : add2DArray([], kfs[i].value, startValue, -1); - } - } - } - }; - - Track.prototype.step = function (target, percent) { - if (this._finished) { - return; - } - - if (this._additiveTrack && this._additiveTrack._finished) { - this._additiveTrack = null; - } - - var isAdditive = this._additiveTrack != null; - var valueKey = isAdditive ? 'additiveValue' : 'value'; - var valType = this.valType; - var keyframes = this.keyframes; - var kfsNum = keyframes.length; - var propName = this.propName; - var isValueColor = valType === VALUE_TYPE_COLOR; - var frameIdx; - var lastFrame = this._lastFr; - var mathMin = Math.min; - var frame; - var nextFrame; - - if (kfsNum === 1) { - frame = nextFrame = keyframes[0]; - } else { - if (percent < 0) { - frameIdx = 0; - } else if (percent < this._lastFrP) { - var start = mathMin(lastFrame + 1, kfsNum - 1); - - for (frameIdx = start; frameIdx >= 0; frameIdx--) { - if (keyframes[frameIdx].percent <= percent) { - break; - } - } - - frameIdx = mathMin(frameIdx, kfsNum - 2); - } else { - for (frameIdx = lastFrame; frameIdx < kfsNum; frameIdx++) { - if (keyframes[frameIdx].percent > percent) { - break; - } - } - - frameIdx = mathMin(frameIdx - 1, kfsNum - 2); - } - - nextFrame = keyframes[frameIdx + 1]; - frame = keyframes[frameIdx]; - } - - if (!(frame && nextFrame)) { - return; - } - - this._lastFr = frameIdx; - this._lastFrP = percent; - var interval = nextFrame.percent - frame.percent; - var w = interval === 0 ? 1 : mathMin((percent - frame.percent) / interval, 1); - - if (nextFrame.easingFunc) { - w = nextFrame.easingFunc(w); - } - - var targetArr = isAdditive ? this._additiveValue : isValueColor ? tmpRgba : target[propName]; - - if ((isArrayValueType(valType) || isValueColor) && !targetArr) { - targetArr = this._additiveValue = []; - } - - if (this.discrete) { - target[propName] = w < 1 ? frame.rawValue : nextFrame.rawValue; - } else if (isArrayValueType(valType)) { - valType === VALUE_TYPE_1D_ARRAY ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w) : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); - } else if (isGradientValueType(valType)) { - var val = frame[valueKey]; - var nextVal_1 = nextFrame[valueKey]; - var isLinearGradient_1 = valType === VALUE_TYPE_LINEAR_GRADIENT; - target[propName] = { - type: isLinearGradient_1 ? 'linear' : 'radial', - x: interpolateNumber$1(val.x, nextVal_1.x, w), - y: interpolateNumber$1(val.y, nextVal_1.y, w), - colorStops: map$1(val.colorStops, function (colorStop, idx) { - var nextColorStop = nextVal_1.colorStops[idx]; - return { - offset: interpolateNumber$1(colorStop.offset, nextColorStop.offset, w), - color: rgba2String(interpolate1DArray([], colorStop.color, nextColorStop.color, w)) - }; - }), - global: nextVal_1.global - }; - - if (isLinearGradient_1) { - target[propName].x2 = interpolateNumber$1(val.x2, nextVal_1.x2, w); - target[propName].y2 = interpolateNumber$1(val.y2, nextVal_1.y2, w); - } else { - target[propName].r = interpolateNumber$1(val.r, nextVal_1.r, w); - } - } else if (isValueColor) { - interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); - - if (!isAdditive) { - target[propName] = rgba2String(targetArr); - } - } else { - var value = interpolateNumber$1(frame[valueKey], nextFrame[valueKey], w); - - if (isAdditive) { - this._additiveValue = value; - } else { - target[propName] = value; - } - } - - if (isAdditive) { - this._addToTarget(target); - } - }; - - Track.prototype._addToTarget = function (target) { - var valType = this.valType; - var propName = this.propName; - var additiveValue = this._additiveValue; - - if (valType === VALUE_TYPE_NUMBER) { - target[propName] = target[propName] + additiveValue; - } else if (valType === VALUE_TYPE_COLOR) { - parse(target[propName], tmpRgba); - add1DArray(tmpRgba, tmpRgba, additiveValue, 1); - target[propName] = rgba2String(tmpRgba); - } else if (valType === VALUE_TYPE_1D_ARRAY) { - add1DArray(target[propName], target[propName], additiveValue, 1); - } else if (valType === VALUE_TYPE_2D_ARRAY) { - add2DArray(target[propName], target[propName], additiveValue, 1); - } - }; - - return Track; - }(); - - var Animator = function () { - function Animator(target, loop, allowDiscreteAnimation, additiveTo) { - this._tracks = {}; - this._trackKeys = []; - this._maxTime = 0; - this._started = 0; - this._clip = null; - this._target = target; - this._loop = loop; - - if (loop && additiveTo) { - logError('Can\' use additive animation on looped animation.'); - return; - } - - this._additiveAnimators = additiveTo; - this._allowDiscrete = allowDiscreteAnimation; - } - - Animator.prototype.getMaxTime = function () { - return this._maxTime; - }; - - Animator.prototype.getDelay = function () { - return this._delay; - }; - - Animator.prototype.getLoop = function () { - return this._loop; - }; - - Animator.prototype.getTarget = function () { - return this._target; - }; - - Animator.prototype.changeTarget = function (target) { - this._target = target; - }; - - Animator.prototype.when = function (time, props, easing) { - return this.whenWithKeys(time, props, keys(props), easing); - }; - - Animator.prototype.whenWithKeys = function (time, props, propNames, easing) { - var tracks = this._tracks; - - for (var i = 0; i < propNames.length; i++) { - var propName = propNames[i]; - var track = tracks[propName]; - - if (!track) { - track = tracks[propName] = new Track(propName); - var initialValue = void 0; - - var additiveTrack = this._getAdditiveTrack(propName); - - if (additiveTrack) { - var addtiveTrackKfs = additiveTrack.keyframes; - var lastFinalKf = addtiveTrackKfs[addtiveTrackKfs.length - 1]; - initialValue = lastFinalKf && lastFinalKf.value; - - if (additiveTrack.valType === VALUE_TYPE_COLOR && initialValue) { - initialValue = rgba2String(initialValue); - } - } else { - initialValue = this._target[propName]; - } - - if (initialValue == null) { - continue; - } - - if (time > 0) { - track.addKeyframe(0, cloneValue(initialValue), easing); - } - - this._trackKeys.push(propName); - } - - track.addKeyframe(time, cloneValue(props[propName]), easing); - } - - this._maxTime = Math.max(this._maxTime, time); - return this; - }; - - Animator.prototype.pause = function () { - this._clip.pause(); - - this._paused = true; - }; - - Animator.prototype.resume = function () { - this._clip.resume(); - - this._paused = false; - }; - - Animator.prototype.isPaused = function () { - return !!this._paused; - }; - - Animator.prototype.duration = function (duration) { - this._maxTime = duration; - this._force = true; - return this; - }; - - Animator.prototype._doneCallback = function () { - this._setTracksFinished(); - - this._clip = null; - var doneList = this._doneCbs; - - if (doneList) { - var len = doneList.length; - - for (var i = 0; i < len; i++) { - doneList[i].call(this); - } - } - }; - - Animator.prototype._abortedCallback = function () { - this._setTracksFinished(); - - var animation = this.animation; - var abortedList = this._abortedCbs; - - if (animation) { - animation.removeClip(this._clip); - } - - this._clip = null; - - if (abortedList) { - for (var i = 0; i < abortedList.length; i++) { - abortedList[i].call(this); - } - } - }; - - Animator.prototype._setTracksFinished = function () { - var tracks = this._tracks; - var tracksKeys = this._trackKeys; - - for (var i = 0; i < tracksKeys.length; i++) { - tracks[tracksKeys[i]].setFinished(); - } - }; - - Animator.prototype._getAdditiveTrack = function (trackName) { - var additiveTrack; - var additiveAnimators = this._additiveAnimators; - - if (additiveAnimators) { - for (var i = 0; i < additiveAnimators.length; i++) { - var track = additiveAnimators[i].getTrack(trackName); - - if (track) { - additiveTrack = track; - } - } - } - - return additiveTrack; - }; - - Animator.prototype.start = function (easing) { - if (this._started > 0) { - return; - } - - this._started = 1; - var self = this; - var tracks = []; - var maxTime = this._maxTime || 0; - - for (var i = 0; i < this._trackKeys.length; i++) { - var propName = this._trackKeys[i]; - var track = this._tracks[propName]; - - var additiveTrack = this._getAdditiveTrack(propName); - - var kfs = track.keyframes; - var kfsNum = kfs.length; - track.prepare(maxTime, additiveTrack); - - if (track.needsAnimate()) { - if (!this._allowDiscrete && track.discrete) { - var lastKf = kfs[kfsNum - 1]; - - if (lastKf) { - self._target[track.propName] = lastKf.rawValue; - } - - track.setFinished(); - } else { - tracks.push(track); - } - } - } - - if (tracks.length || this._force) { - var clip = new Clip({ - life: maxTime, - loop: this._loop, - delay: this._delay || 0, - onframe: function (percent) { - self._started = 2; - var additiveAnimators = self._additiveAnimators; - - if (additiveAnimators) { - var stillHasAdditiveAnimator = false; - - for (var i = 0; i < additiveAnimators.length; i++) { - if (additiveAnimators[i]._clip) { - stillHasAdditiveAnimator = true; - break; - } - } - - if (!stillHasAdditiveAnimator) { - self._additiveAnimators = null; - } - } - - for (var i = 0; i < tracks.length; i++) { - tracks[i].step(self._target, percent); - } - - var onframeList = self._onframeCbs; - - if (onframeList) { - for (var i = 0; i < onframeList.length; i++) { - onframeList[i](self._target, percent); - } - } - }, - ondestroy: function () { - self._doneCallback(); - } - }); - this._clip = clip; - - if (this.animation) { - this.animation.addClip(clip); - } - - if (easing) { - clip.setEasing(easing); - } - } else { - this._doneCallback(); - } - - return this; - }; - - Animator.prototype.stop = function (forwardToLast) { - if (!this._clip) { - return; - } - - var clip = this._clip; - - if (forwardToLast) { - clip.onframe(1); - } - - this._abortedCallback(); - }; - - Animator.prototype.delay = function (time) { - this._delay = time; - return this; - }; - - Animator.prototype.during = function (cb) { - if (cb) { - if (!this._onframeCbs) { - this._onframeCbs = []; - } - - this._onframeCbs.push(cb); - } - - return this; - }; - - Animator.prototype.done = function (cb) { - if (cb) { - if (!this._doneCbs) { - this._doneCbs = []; - } - - this._doneCbs.push(cb); - } - - return this; - }; - - Animator.prototype.aborted = function (cb) { - if (cb) { - if (!this._abortedCbs) { - this._abortedCbs = []; - } - - this._abortedCbs.push(cb); - } - - return this; - }; - - Animator.prototype.getClip = function () { - return this._clip; - }; - - Animator.prototype.getTrack = function (propName) { - return this._tracks[propName]; - }; - - Animator.prototype.getTracks = function () { - var _this = this; - - return map$1(this._trackKeys, function (key) { - return _this._tracks[key]; - }); - }; - - Animator.prototype.stopTracks = function (propNames, forwardToLast) { - if (!propNames.length || !this._clip) { - return true; - } - - var tracks = this._tracks; - var tracksKeys = this._trackKeys; - - for (var i = 0; i < propNames.length; i++) { - var track = tracks[propNames[i]]; - - if (track && !track.isFinished()) { - if (forwardToLast) { - track.step(this._target, 1); - } else if (this._started === 1) { - track.step(this._target, 0); - } - - track.setFinished(); - } - } - - var allAborted = true; - - for (var i = 0; i < tracksKeys.length; i++) { - if (!tracks[tracksKeys[i]].isFinished()) { - allAborted = false; - break; - } - } - - if (allAborted) { - this._abortedCallback(); - } - - return allAborted; - }; - - Animator.prototype.saveTo = function (target, trackKeys, firstOrLast) { - if (!target) { - return; - } - - trackKeys = trackKeys || this._trackKeys; - - for (var i = 0; i < trackKeys.length; i++) { - var propName = trackKeys[i]; - var track = this._tracks[propName]; - - if (!track || track.isFinished()) { - continue; - } - - var kfs = track.keyframes; - var kf = kfs[firstOrLast ? 0 : kfs.length - 1]; - - if (kf) { - target[propName] = cloneValue(kf.rawValue); - } - } - }; - - Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) { - trackKeys = trackKeys || keys(finalProps); - - for (var i = 0; i < trackKeys.length; i++) { - var propName = trackKeys[i]; - var track = this._tracks[propName]; - - if (!track) { - continue; - } - - var kfs = track.keyframes; - - if (kfs.length > 1) { - var lastKf = kfs.pop(); - track.addKeyframe(lastKf.time, finalProps[propName]); - track.prepare(this._maxTime, track.getAdditiveTrack()); - } - } - }; - - return Animator; - }(); - - function getTime() { - return new Date().getTime(); - } - - var Animation = function (_super) { - __extends(Animation, _super); - - function Animation(opts) { - var _this = _super.call(this) || this; - - _this._running = false; - _this._time = 0; - _this._pausedTime = 0; - _this._pauseStart = 0; - _this._paused = false; - opts = opts || {}; - _this.stage = opts.stage || {}; - return _this; - } - - Animation.prototype.addClip = function (clip) { - if (clip.animation) { - this.removeClip(clip); - } - - if (!this._head) { - this._head = this._tail = clip; - } else { - this._tail.next = clip; - clip.prev = this._tail; - clip.next = null; - this._tail = clip; - } - - clip.animation = this; - }; - - Animation.prototype.addAnimator = function (animator) { - animator.animation = this; - var clip = animator.getClip(); - - if (clip) { - this.addClip(clip); - } - }; - - Animation.prototype.removeClip = function (clip) { - if (!clip.animation) { - return; - } - - var prev = clip.prev; - var next = clip.next; - - if (prev) { - prev.next = next; - } else { - this._head = next; - } - - if (next) { - next.prev = prev; - } else { - this._tail = prev; - } - - clip.next = clip.prev = clip.animation = null; - }; - - Animation.prototype.removeAnimator = function (animator) { - var clip = animator.getClip(); - - if (clip) { - this.removeClip(clip); - } - - animator.animation = null; - }; - - Animation.prototype.update = function (notTriggerFrameAndStageUpdate) { - var time = getTime() - this._pausedTime; - - var delta = time - this._time; - var clip = this._head; - - while (clip) { - var nextClip = clip.next; - var finished = clip.step(time, delta); - - if (finished) { - clip.ondestroy(); - this.removeClip(clip); - clip = nextClip; - } else { - clip = nextClip; - } - } - - this._time = time; - - if (!notTriggerFrameAndStageUpdate) { - this.trigger('frame', delta); - this.stage.update && this.stage.update(); - } - }; - - Animation.prototype._startLoop = function () { - var self = this; - this._running = true; - - function step() { - if (self._running) { - requestAnimationFrame$1(step); - !self._paused && self.update(); - } - } - - requestAnimationFrame$1(step); - }; - - Animation.prototype.start = function () { - if (this._running) { - return; - } - - this._time = getTime(); - this._pausedTime = 0; - - this._startLoop(); - }; - - Animation.prototype.stop = function () { - this._running = false; - }; - - Animation.prototype.pause = function () { - if (!this._paused) { - this._pauseStart = getTime(); - this._paused = true; - } - }; - - Animation.prototype.resume = function () { - if (this._paused) { - this._pausedTime += getTime() - this._pauseStart; - this._paused = false; - } - }; - - Animation.prototype.clear = function () { - var clip = this._head; - - while (clip) { - var nextClip = clip.next; - clip.prev = clip.next = clip.animation = null; - clip = nextClip; - } - - this._head = this._tail = null; - }; - - Animation.prototype.isFinished = function () { - return this._head == null; - }; - - Animation.prototype.animate = function (target, options) { - options = options || {}; - this.start(); - var animator = new Animator(target, options.loop); - this.addAnimator(animator); - return animator; - }; - - return Animation; - }(Eventful); - - var TOUCH_CLICK_DELAY = 300; - var globalEventSupported = env.domSupported; - - var localNativeListenerNames = function () { - var mouseHandlerNames = ['click', 'dblclick', 'mousewheel', 'wheel', 'mouseout', 'mouseup', 'mousedown', 'mousemove', 'contextmenu']; - var touchHandlerNames = ['touchstart', 'touchend', 'touchmove']; - var pointerEventNameMap = { - pointerdown: 1, - pointerup: 1, - pointermove: 1, - pointerout: 1 - }; - var pointerHandlerNames = map$1(mouseHandlerNames, function (name) { - var nm = name.replace('mouse', 'pointer'); - return pointerEventNameMap.hasOwnProperty(nm) ? nm : name; - }); - return { - mouse: mouseHandlerNames, - touch: touchHandlerNames, - pointer: pointerHandlerNames - }; - }(); - - var globalNativeListenerNames = { - mouse: ['mousemove', 'mouseup'], - pointer: ['pointermove', 'pointerup'] - }; - var wheelEventSupported = false; - - function isPointerFromTouch(event) { - var pointerType = event.pointerType; - return pointerType === 'pen' || pointerType === 'touch'; - } - - function setTouchTimer(scope) { - scope.touching = true; - - if (scope.touchTimer != null) { - clearTimeout(scope.touchTimer); - scope.touchTimer = null; - } - - scope.touchTimer = setTimeout(function () { - scope.touching = false; - scope.touchTimer = null; - }, 700); - } - - function markTouch(event) { - event && (event.zrByTouch = true); - } - - function normalizeGlobalEvent(instance, event) { - return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true); - } - - function isLocalEl(instance, el) { - var elTmp = el; - var isLocal = false; - - while (elTmp && elTmp.nodeType !== 9 && !(isLocal = elTmp.domBelongToZr || elTmp !== el && elTmp === instance.painterRoot)) { - elTmp = elTmp.parentNode; - } - - return isLocal; - } - - var FakeGlobalEvent = function () { - function FakeGlobalEvent(instance, event) { - this.stopPropagation = noop; - this.stopImmediatePropagation = noop; - this.preventDefault = noop; - this.type = event.type; - this.target = this.currentTarget = instance.dom; - this.pointerType = event.pointerType; - this.clientX = event.clientX; - this.clientY = event.clientY; - } - - return FakeGlobalEvent; - }(); - - var localDOMHandlers = { - mousedown: function (event) { - event = normalizeEvent(this.dom, event); - this.__mayPointerCapture = [event.zrX, event.zrY]; - this.trigger('mousedown', event); - }, - mousemove: function (event) { - event = normalizeEvent(this.dom, event); - var downPoint = this.__mayPointerCapture; - - if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) { - this.__togglePointerCapture(true); - } - - this.trigger('mousemove', event); - }, - mouseup: function (event) { - event = normalizeEvent(this.dom, event); - - this.__togglePointerCapture(false); - - this.trigger('mouseup', event); - }, - mouseout: function (event) { - event = normalizeEvent(this.dom, event); - var element = event.toElement || event.relatedTarget; - - if (!isLocalEl(this, element)) { - if (this.__pointerCapturing) { - event.zrEventControl = 'no_globalout'; - } - - this.trigger('mouseout', event); - } - }, - wheel: function (event) { - wheelEventSupported = true; - event = normalizeEvent(this.dom, event); - this.trigger('mousewheel', event); - }, - mousewheel: function (event) { - if (wheelEventSupported) { - return; - } - - event = normalizeEvent(this.dom, event); - this.trigger('mousewheel', event); - }, - touchstart: function (event) { - event = normalizeEvent(this.dom, event); - markTouch(event); - this.__lastTouchMoment = new Date(); - this.handler.processGesture(event, 'start'); - localDOMHandlers.mousemove.call(this, event); - localDOMHandlers.mousedown.call(this, event); - }, - touchmove: function (event) { - event = normalizeEvent(this.dom, event); - markTouch(event); - this.handler.processGesture(event, 'change'); - localDOMHandlers.mousemove.call(this, event); - }, - touchend: function (event) { - event = normalizeEvent(this.dom, event); - markTouch(event); - this.handler.processGesture(event, 'end'); - localDOMHandlers.mouseup.call(this, event); - - if (+new Date() - +this.__lastTouchMoment < TOUCH_CLICK_DELAY) { - localDOMHandlers.click.call(this, event); - } - }, - pointerdown: function (event) { - localDOMHandlers.mousedown.call(this, event); - }, - pointermove: function (event) { - if (!isPointerFromTouch(event)) { - localDOMHandlers.mousemove.call(this, event); - } - }, - pointerup: function (event) { - localDOMHandlers.mouseup.call(this, event); - }, - pointerout: function (event) { - if (!isPointerFromTouch(event)) { - localDOMHandlers.mouseout.call(this, event); - } - } - }; - each$4(['click', 'dblclick', 'contextmenu'], function (name) { - localDOMHandlers[name] = function (event) { - event = normalizeEvent(this.dom, event); - this.trigger(name, event); - }; - }); - var globalDOMHandlers = { - pointermove: function (event) { - if (!isPointerFromTouch(event)) { - globalDOMHandlers.mousemove.call(this, event); - } - }, - pointerup: function (event) { - globalDOMHandlers.mouseup.call(this, event); - }, - mousemove: function (event) { - this.trigger('mousemove', event); - }, - mouseup: function (event) { - var pointerCaptureReleasing = this.__pointerCapturing; - - this.__togglePointerCapture(false); - - this.trigger('mouseup', event); - - if (pointerCaptureReleasing) { - event.zrEventControl = 'only_globalout'; - this.trigger('mouseout', event); - } - } - }; - - function mountLocalDOMEventListeners(instance, scope) { - var domHandlers = scope.domHandlers; - - if (env.pointerEventsSupported) { - each$4(localNativeListenerNames.pointer, function (nativeEventName) { - mountSingleDOMEventListener(scope, nativeEventName, function (event) { - domHandlers[nativeEventName].call(instance, event); - }); - }); - } else { - if (env.touchEventsSupported) { - each$4(localNativeListenerNames.touch, function (nativeEventName) { - mountSingleDOMEventListener(scope, nativeEventName, function (event) { - domHandlers[nativeEventName].call(instance, event); - setTouchTimer(scope); - }); - }); - } - - each$4(localNativeListenerNames.mouse, function (nativeEventName) { - mountSingleDOMEventListener(scope, nativeEventName, function (event) { - event = getNativeEvent(event); - - if (!scope.touching) { - domHandlers[nativeEventName].call(instance, event); - } - }); - }); - } - } - - function mountGlobalDOMEventListeners(instance, scope) { - if (env.pointerEventsSupported) { - each$4(globalNativeListenerNames.pointer, mount); - } else if (!env.touchEventsSupported) { - each$4(globalNativeListenerNames.mouse, mount); - } - - function mount(nativeEventName) { - function nativeEventListener(event) { - event = getNativeEvent(event); - - if (!isLocalEl(instance, event.target)) { - event = normalizeGlobalEvent(instance, event); - scope.domHandlers[nativeEventName].call(instance, event); - } - } - - mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { - capture: true - }); - } - } - - function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) { - scope.mounted[nativeEventName] = listener; - scope.listenerOpts[nativeEventName] = opt; - addEventListener(scope.domTarget, nativeEventName, listener, opt); - } - - function unmountDOMEventListeners(scope) { - var mounted = scope.mounted; - - for (var nativeEventName in mounted) { - if (mounted.hasOwnProperty(nativeEventName)) { - removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]); - } - } - - scope.mounted = {}; - } - - var DOMHandlerScope = function () { - function DOMHandlerScope(domTarget, domHandlers) { - this.mounted = {}; - this.listenerOpts = {}; - this.touching = false; - this.domTarget = domTarget; - this.domHandlers = domHandlers; - } - - return DOMHandlerScope; - }(); - - var HandlerDomProxy = function (_super) { - __extends(HandlerDomProxy, _super); - - function HandlerDomProxy(dom, painterRoot) { - var _this = _super.call(this) || this; - - _this.__pointerCapturing = false; - _this.dom = dom; - _this.painterRoot = painterRoot; - _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers); - - if (globalEventSupported) { - _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers); - } - - mountLocalDOMEventListeners(_this, _this._localHandlerScope); - return _this; - } - - HandlerDomProxy.prototype.dispose = function () { - unmountDOMEventListeners(this._localHandlerScope); - - if (globalEventSupported) { - unmountDOMEventListeners(this._globalHandlerScope); - } - }; - - HandlerDomProxy.prototype.setCursor = function (cursorStyle) { - this.dom.style && (this.dom.style.cursor = cursorStyle || 'default'); - }; - - HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) { - this.__mayPointerCapture = null; - - if (globalEventSupported && +this.__pointerCapturing ^ +isPointerCapturing) { - this.__pointerCapturing = isPointerCapturing; - var globalHandlerScope = this._globalHandlerScope; - isPointerCapturing ? mountGlobalDOMEventListeners(this, globalHandlerScope) : unmountDOMEventListeners(globalHandlerScope); - } - }; - - return HandlerDomProxy; - }(Eventful); - - var dpr = 1; - - if (env.hasGlobalWindow) { - dpr = Math.max(window.devicePixelRatio || window.screen && window.screen.deviceXDPI / window.screen.logicalXDPI || 1, 1); - } - - var devicePixelRatio = dpr; - var DARK_MODE_THRESHOLD = 0.4; - var DARK_LABEL_COLOR = '#333'; - var LIGHT_LABEL_COLOR = '#ccc'; - var LIGHTER_LABEL_COLOR = '#eee'; - var mIdentity = identity; - var EPSILON$2 = 5e-5; - - function isNotAroundZero(val) { - return val > EPSILON$2 || val < -EPSILON$2; - } - - var scaleTmp = []; - var tmpTransform = []; - var originTransform = create(); - var abs = Math.abs; - - var Transformable = function () { - function Transformable() {} - - Transformable.prototype.getLocalTransform = function (m) { - return Transformable.getLocalTransform(this, m); - }; - - Transformable.prototype.setPosition = function (arr) { - this.x = arr[0]; - this.y = arr[1]; - }; - - Transformable.prototype.setScale = function (arr) { - this.scaleX = arr[0]; - this.scaleY = arr[1]; - }; - - Transformable.prototype.setSkew = function (arr) { - this.skewX = arr[0]; - this.skewY = arr[1]; - }; - - Transformable.prototype.setOrigin = function (arr) { - this.originX = arr[0]; - this.originY = arr[1]; - }; - - Transformable.prototype.needLocalTransform = function () { - return isNotAroundZero(this.rotation) || isNotAroundZero(this.x) || isNotAroundZero(this.y) || isNotAroundZero(this.scaleX - 1) || isNotAroundZero(this.scaleY - 1) || isNotAroundZero(this.skewX) || isNotAroundZero(this.skewY); - }; - - Transformable.prototype.updateTransform = function () { - var parentTransform = this.parent && this.parent.transform; - var needLocalTransform = this.needLocalTransform(); - var m = this.transform; - - if (!(needLocalTransform || parentTransform)) { - if (m) { - mIdentity(m); - this.invTransform = null; - } - - return; - } - - m = m || create(); - - if (needLocalTransform) { - this.getLocalTransform(m); - } else { - mIdentity(m); - } - - if (parentTransform) { - if (needLocalTransform) { - mul(m, parentTransform, m); - } else { - copy(m, parentTransform); - } - } - - this.transform = m; - - this._resolveGlobalScaleRatio(m); - }; - - Transformable.prototype._resolveGlobalScaleRatio = function (m) { - var globalScaleRatio = this.globalScaleRatio; - - if (globalScaleRatio != null && globalScaleRatio !== 1) { - this.getGlobalScale(scaleTmp); - var relX = scaleTmp[0] < 0 ? -1 : 1; - var relY = scaleTmp[1] < 0 ? -1 : 1; - var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0; - var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0; - m[0] *= sx; - m[1] *= sx; - m[2] *= sy; - m[3] *= sy; - } - - this.invTransform = this.invTransform || create(); - invert(this.invTransform, m); - }; - - Transformable.prototype.getComputedTransform = function () { - var transformNode = this; - var ancestors = []; - - while (transformNode) { - ancestors.push(transformNode); - transformNode = transformNode.parent; - } - - while (transformNode = ancestors.pop()) { - transformNode.updateTransform(); - } - - return this.transform; - }; - - Transformable.prototype.setLocalTransform = function (m) { - if (!m) { - return; - } - - var sx = m[0] * m[0] + m[1] * m[1]; - var sy = m[2] * m[2] + m[3] * m[3]; - var rotation = Math.atan2(m[1], m[0]); - var shearX = Math.PI / 2 + rotation - Math.atan2(m[3], m[2]); - sy = Math.sqrt(sy) * Math.cos(shearX); - sx = Math.sqrt(sx); - this.skewX = shearX; - this.skewY = 0; - this.rotation = -rotation; - this.x = +m[4]; - this.y = +m[5]; - this.scaleX = sx; - this.scaleY = sy; - this.originX = 0; - this.originY = 0; - }; - - Transformable.prototype.decomposeTransform = function () { - if (!this.transform) { - return; - } - - var parent = this.parent; - var m = this.transform; - - if (parent && parent.transform) { - parent.invTransform = parent.invTransform || create(); - mul(tmpTransform, parent.invTransform, m); - m = tmpTransform; - } - - var ox = this.originX; - var oy = this.originY; - - if (ox || oy) { - originTransform[4] = ox; - originTransform[5] = oy; - mul(tmpTransform, m, originTransform); - tmpTransform[4] -= ox; - tmpTransform[5] -= oy; - m = tmpTransform; - } - - this.setLocalTransform(m); - }; - - Transformable.prototype.getGlobalScale = function (out) { - var m = this.transform; - out = out || []; - - if (!m) { - out[0] = 1; - out[1] = 1; - return out; - } - - out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]); - out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]); - - if (m[0] < 0) { - out[0] = -out[0]; - } - - if (m[3] < 0) { - out[1] = -out[1]; - } - - return out; - }; - - Transformable.prototype.transformCoordToLocal = function (x, y) { - var v2 = [x, y]; - var invTransform = this.invTransform; - - if (invTransform) { - applyTransform$1(v2, v2, invTransform); - } - - return v2; - }; - - Transformable.prototype.transformCoordToGlobal = function (x, y) { - var v2 = [x, y]; - var transform = this.transform; - - if (transform) { - applyTransform$1(v2, v2, transform); - } - - return v2; - }; - - Transformable.prototype.getLineScale = function () { - var m = this.transform; - return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) : 1; - }; - - Transformable.prototype.copyTransform = function (source) { - copyTransform(this, source); - }; - - Transformable.getLocalTransform = function (target, m) { - m = m || []; - var ox = target.originX || 0; - var oy = target.originY || 0; - var sx = target.scaleX; - var sy = target.scaleY; - var ax = target.anchorX; - var ay = target.anchorY; - var rotation = target.rotation || 0; - var x = target.x; - var y = target.y; - var skewX = target.skewX ? Math.tan(target.skewX) : 0; - var skewY = target.skewY ? Math.tan(-target.skewY) : 0; - - if (ox || oy || ax || ay) { - var dx = ox + ax; - var dy = oy + ay; - m[4] = -dx * sx - skewX * dy * sy; - m[5] = -dy * sy - skewY * dx * sx; - } else { - m[4] = m[5] = 0; - } - - m[0] = sx; - m[3] = sy; - m[1] = skewY * sx; - m[2] = skewX * sy; - rotation && rotate(m, m, rotation); - m[4] += ox + x; - m[5] += oy + y; - return m; - }; - - Transformable.initDefaultProps = function () { - var proto = Transformable.prototype; - proto.scaleX = proto.scaleY = proto.globalScaleRatio = 1; - proto.x = proto.y = proto.originX = proto.originY = proto.skewX = proto.skewY = proto.rotation = proto.anchorX = proto.anchorY = 0; - }(); - - return Transformable; - }(); - - var TRANSFORMABLE_PROPS = ['x', 'y', 'originX', 'originY', 'anchorX', 'anchorY', 'rotation', 'scaleX', 'scaleY', 'skewX', 'skewY']; - - function copyTransform(target, source) { - for (var i = 0; i < TRANSFORMABLE_PROPS.length; i++) { - var propName = TRANSFORMABLE_PROPS[i]; - target[propName] = source[propName]; - } - } - - var textWidthCache = {}; - - function getWidth(text, font) { - font = font || DEFAULT_FONT; - var cacheOfFont = textWidthCache[font]; - - if (!cacheOfFont) { - cacheOfFont = textWidthCache[font] = new LRU(500); - } - - var width = cacheOfFont.get(text); - - if (width == null) { - width = platformApi.measureText(text, font).width; - cacheOfFont.put(text, width); - } - - return width; - } - - function innerGetBoundingRect(text, font, textAlign, textBaseline) { - var width = getWidth(text, font); - var height = getLineHeight(font); - var x = adjustTextX(0, width, textAlign); - var y = adjustTextY(0, height, textBaseline); - var rect = new BoundingRect(x, y, width, height); - return rect; - } - - function getBoundingRect(text, font, textAlign, textBaseline) { - var textLines = ((text || '') + '').split('\n'); - var len = textLines.length; - - if (len === 1) { - return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline); - } else { - var uniondRect = new BoundingRect(0, 0, 0, 0); - - for (var i = 0; i < textLines.length; i++) { - var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline); - i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect); - } - - return uniondRect; - } - } - - function adjustTextX(x, width, textAlign) { - if (textAlign === 'right') { - x -= width; - } else if (textAlign === 'center') { - x -= width / 2; - } - - return x; - } - - function adjustTextY(y, height, verticalAlign) { - if (verticalAlign === 'middle') { - y -= height / 2; - } else if (verticalAlign === 'bottom') { - y -= height; - } - - return y; - } - - function getLineHeight(font) { - return getWidth('国', font); - } - - function parsePercent$1(value, maxValue) { - if (typeof value === 'string') { - if (value.lastIndexOf('%') >= 0) { - return parseFloat(value) / 100 * maxValue; - } - - return parseFloat(value); - } - - return value; - } - - function calculateTextPosition(out, opts, rect) { - var textPosition = opts.position || 'inside'; - var distance = opts.distance != null ? opts.distance : 5; - var height = rect.height; - var width = rect.width; - var halfHeight = height / 2; - var x = rect.x; - var y = rect.y; - var textAlign = 'left'; - var textVerticalAlign = 'top'; - - if (textPosition instanceof Array) { - x += parsePercent$1(textPosition[0], rect.width); - y += parsePercent$1(textPosition[1], rect.height); - textAlign = null; - textVerticalAlign = null; - } else { - switch (textPosition) { - case 'left': - x -= distance; - y += halfHeight; - textAlign = 'right'; - textVerticalAlign = 'middle'; - break; - - case 'right': - x += distance + width; - y += halfHeight; - textVerticalAlign = 'middle'; - break; - - case 'top': - x += width / 2; - y -= distance; - textAlign = 'center'; - textVerticalAlign = 'bottom'; - break; - - case 'bottom': - x += width / 2; - y += height + distance; - textAlign = 'center'; - break; - - case 'inside': - x += width / 2; - y += halfHeight; - textAlign = 'center'; - textVerticalAlign = 'middle'; - break; - - case 'insideLeft': - x += distance; - y += halfHeight; - textVerticalAlign = 'middle'; - break; - - case 'insideRight': - x += width - distance; - y += halfHeight; - textAlign = 'right'; - textVerticalAlign = 'middle'; - break; - - case 'insideTop': - x += width / 2; - y += distance; - textAlign = 'center'; - break; - - case 'insideBottom': - x += width / 2; - y += height - distance; - textAlign = 'center'; - textVerticalAlign = 'bottom'; - break; - - case 'insideTopLeft': - x += distance; - y += distance; - break; - - case 'insideTopRight': - x += width - distance; - y += distance; - textAlign = 'right'; - break; - - case 'insideBottomLeft': - x += distance; - y += height - distance; - textVerticalAlign = 'bottom'; - break; - - case 'insideBottomRight': - x += width - distance; - y += height - distance; - textAlign = 'right'; - textVerticalAlign = 'bottom'; - break; - } - } - - out = out || {}; - out.x = x; - out.y = y; - out.align = textAlign; - out.verticalAlign = textVerticalAlign; - return out; - } - - var PRESERVED_NORMAL_STATE = '__zr_normal__'; - var PRIMARY_STATES_KEYS$1 = TRANSFORMABLE_PROPS.concat(['ignore']); - var DEFAULT_ANIMATABLE_MAP = reduce(TRANSFORMABLE_PROPS, function (obj, key) { - obj[key] = true; - return obj; - }, { - ignore: false - }); - var tmpTextPosCalcRes = {}; - var tmpBoundingRect = new BoundingRect(0, 0, 0, 0); - - var Element = function () { - function Element(props) { - this.id = guid(); - this.animators = []; - this.currentStates = []; - this.states = {}; - - this._init(props); - } - - Element.prototype._init = function (props) { - this.attr(props); - }; - - Element.prototype.drift = function (dx, dy, e) { - switch (this.draggable) { - case 'horizontal': - dy = 0; - break; - - case 'vertical': - dx = 0; - break; - } - - var m = this.transform; - - if (!m) { - m = this.transform = [1, 0, 0, 1, 0, 0]; - } - - m[4] += dx; - m[5] += dy; - this.decomposeTransform(); - this.markRedraw(); - }; - - Element.prototype.beforeUpdate = function () {}; - - Element.prototype.afterUpdate = function () {}; - - Element.prototype.update = function () { - this.updateTransform(); - - if (this.__dirty) { - this.updateInnerText(); - } - }; - - Element.prototype.updateInnerText = function (forceUpdate) { - var textEl = this._textContent; - - if (textEl && (!textEl.ignore || forceUpdate)) { - if (!this.textConfig) { - this.textConfig = {}; - } - - var textConfig = this.textConfig; - var isLocal = textConfig.local; - var innerTransformable = textEl.innerTransformable; - var textAlign = void 0; - var textVerticalAlign = void 0; - var textStyleChanged = false; - innerTransformable.parent = isLocal ? this : null; - var innerOrigin = false; - innerTransformable.copyTransform(textEl); - - if (textConfig.position != null) { - var layoutRect = tmpBoundingRect; - - if (textConfig.layoutRect) { - layoutRect.copy(textConfig.layoutRect); - } else { - layoutRect.copy(this.getBoundingRect()); - } - - if (!isLocal) { - layoutRect.applyTransform(this.transform); - } - - if (this.calculateTextPosition) { - this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); - } else { - calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); - } - - innerTransformable.x = tmpTextPosCalcRes.x; - innerTransformable.y = tmpTextPosCalcRes.y; - textAlign = tmpTextPosCalcRes.align; - textVerticalAlign = tmpTextPosCalcRes.verticalAlign; - var textOrigin = textConfig.origin; - - if (textOrigin && textConfig.rotation != null) { - var relOriginX = void 0; - var relOriginY = void 0; - - if (textOrigin === 'center') { - relOriginX = layoutRect.width * 0.5; - relOriginY = layoutRect.height * 0.5; - } else { - relOriginX = parsePercent$1(textOrigin[0], layoutRect.width); - relOriginY = parsePercent$1(textOrigin[1], layoutRect.height); - } - - innerOrigin = true; - innerTransformable.originX = -innerTransformable.x + relOriginX + (isLocal ? 0 : layoutRect.x); - innerTransformable.originY = -innerTransformable.y + relOriginY + (isLocal ? 0 : layoutRect.y); - } - } - - if (textConfig.rotation != null) { - innerTransformable.rotation = textConfig.rotation; - } - - var textOffset = textConfig.offset; - - if (textOffset) { - innerTransformable.x += textOffset[0]; - innerTransformable.y += textOffset[1]; - - if (!innerOrigin) { - innerTransformable.originX = -textOffset[0]; - innerTransformable.originY = -textOffset[1]; - } - } - - var isInside = textConfig.inside == null ? typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0 : textConfig.inside; - var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {}); - var textFill = void 0; - var textStroke = void 0; - var autoStroke = void 0; - - if (isInside && this.canBeInsideText()) { - textFill = textConfig.insideFill; - textStroke = textConfig.insideStroke; - - if (textFill == null || textFill === 'auto') { - textFill = this.getInsideTextFill(); - } - - if (textStroke == null || textStroke === 'auto') { - textStroke = this.getInsideTextStroke(textFill); - autoStroke = true; - } - } else { - textFill = textConfig.outsideFill; - textStroke = textConfig.outsideStroke; - - if (textFill == null || textFill === 'auto') { - textFill = this.getOutsideFill(); - } - - if (textStroke == null || textStroke === 'auto') { - textStroke = this.getOutsideStroke(textFill); - autoStroke = true; - } - } - - textFill = textFill || '#000'; - - if (textFill !== innerTextDefaultStyle.fill || textStroke !== innerTextDefaultStyle.stroke || autoStroke !== innerTextDefaultStyle.autoStroke || textAlign !== innerTextDefaultStyle.align || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) { - textStyleChanged = true; - innerTextDefaultStyle.fill = textFill; - innerTextDefaultStyle.stroke = textStroke; - innerTextDefaultStyle.autoStroke = autoStroke; - innerTextDefaultStyle.align = textAlign; - innerTextDefaultStyle.verticalAlign = textVerticalAlign; - textEl.setDefaultTextStyle(innerTextDefaultStyle); - } - - textEl.__dirty |= REDRAW_BIT; - - if (textStyleChanged) { - textEl.dirtyStyle(true); - } - } - }; - - Element.prototype.canBeInsideText = function () { - return true; - }; - - Element.prototype.getInsideTextFill = function () { - return '#fff'; - }; - - Element.prototype.getInsideTextStroke = function (textFill) { - return '#000'; - }; - - Element.prototype.getOutsideFill = function () { - return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR; - }; - - Element.prototype.getOutsideStroke = function (textFill) { - var backgroundColor = this.__zr && this.__zr.getBackgroundColor(); - - var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor); - - if (!colorArr) { - colorArr = [255, 255, 255, 1]; - } - - var alpha = colorArr[3]; - - var isDark = this.__zr.isDarkMode(); - - for (var i = 0; i < 3; i++) { - colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha); - } - - colorArr[3] = 1; - return stringify(colorArr, 'rgba'); - }; - - Element.prototype.traverse = function (cb, context) {}; - - Element.prototype.attrKV = function (key, value) { - if (key === 'textConfig') { - this.setTextConfig(value); - } else if (key === 'textContent') { - this.setTextContent(value); - } else if (key === 'clipPath') { - this.setClipPath(value); - } else if (key === 'extra') { - this.extra = this.extra || {}; - extend(this.extra, value); - } else { - this[key] = value; - } - }; - - Element.prototype.hide = function () { - this.ignore = true; - this.markRedraw(); - }; - - Element.prototype.show = function () { - this.ignore = false; - this.markRedraw(); - }; - - Element.prototype.attr = function (keyOrObj, value) { - if (typeof keyOrObj === 'string') { - this.attrKV(keyOrObj, value); - } else if (isObject$2(keyOrObj)) { - var obj = keyOrObj; - var keysArr = keys(obj); - - for (var i = 0; i < keysArr.length; i++) { - var key = keysArr[i]; - this.attrKV(key, keyOrObj[key]); - } - } - - this.markRedraw(); - return this; - }; - - Element.prototype.saveCurrentToNormalState = function (toState) { - this._innerSaveToNormal(toState); - - var normalState = this._normalState; - - for (var i = 0; i < this.animators.length; i++) { - var animator = this.animators[i]; - var fromStateTransition = animator.__fromStateTransition; - - if (animator.getLoop() || fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) { - continue; - } - - var targetName = animator.targetName; - var target = targetName ? normalState[targetName] : normalState; - animator.saveTo(target); - } - }; - - Element.prototype._innerSaveToNormal = function (toState) { - var normalState = this._normalState; - - if (!normalState) { - normalState = this._normalState = {}; - } - - if (toState.textConfig && !normalState.textConfig) { - normalState.textConfig = this.textConfig; - } - - this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS$1); - }; - - Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) { - for (var i = 0; i < primaryKeys.length; i++) { - var key = primaryKeys[i]; - - if (toState[key] != null && !(key in normalState)) { - normalState[key] = this[key]; - } - } - }; - - Element.prototype.hasState = function () { - return this.currentStates.length > 0; - }; - - Element.prototype.getState = function (name) { - return this.states[name]; - }; - - Element.prototype.ensureState = function (name) { - var states = this.states; - - if (!states[name]) { - states[name] = {}; - } - - return states[name]; - }; - - Element.prototype.clearStates = function (noAnimation) { - this.useState(PRESERVED_NORMAL_STATE, false, noAnimation); - }; - - Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation, forceUseHoverLayer) { - var toNormalState = stateName === PRESERVED_NORMAL_STATE; - var hasStates = this.hasState(); - - if (!hasStates && toNormalState) { - return; - } - - var currentStates = this.currentStates; - var animationCfg = this.stateTransition; - - if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) { - return; - } - - var state; - - if (this.stateProxy && !toNormalState) { - state = this.stateProxy(stateName); - } - - if (!state) { - state = this.states && this.states[stateName]; - } - - if (!state && !toNormalState) { - logError("State " + stateName + " not exists."); - return; - } - - if (!toNormalState) { - this.saveCurrentToNormalState(state); - } - - var useHoverLayer = !!(state && state.hoverLayer || forceUseHoverLayer); - - if (useHoverLayer) { - this._toggleHoverLayerFlag(true); - } - - this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); - - var textContent = this._textContent; - var textGuide = this._textGuide; - - if (textContent) { - textContent.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer); - } - - if (textGuide) { - textGuide.useState(stateName, keepCurrentStates, noAnimation, useHoverLayer); - } - - if (toNormalState) { - this.currentStates = []; - this._normalState = {}; - } else { - if (!keepCurrentStates) { - this.currentStates = [stateName]; - } else { - this.currentStates.push(stateName); - } - } - - this._updateAnimationTargets(); - - this.markRedraw(); - - if (!useHoverLayer && this.__inHover) { - this._toggleHoverLayerFlag(false); - - this.__dirty &= ~REDRAW_BIT; - } - - return state; - }; - - Element.prototype.useStates = function (states, noAnimation, forceUseHoverLayer) { - if (!states.length) { - this.clearStates(); - } else { - var stateObjects = []; - var currentStates = this.currentStates; - var len = states.length; - var notChange = len === currentStates.length; - - if (notChange) { - for (var i = 0; i < len; i++) { - if (states[i] !== currentStates[i]) { - notChange = false; - break; - } - } - } - - if (notChange) { - return; - } - - for (var i = 0; i < len; i++) { - var stateName = states[i]; - var stateObj = void 0; - - if (this.stateProxy) { - stateObj = this.stateProxy(stateName, states); - } - - if (!stateObj) { - stateObj = this.states[stateName]; - } - - if (stateObj) { - stateObjects.push(stateObj); - } - } - - var lastStateObj = stateObjects[len - 1]; - var useHoverLayer = !!(lastStateObj && lastStateObj.hoverLayer || forceUseHoverLayer); - - if (useHoverLayer) { - this._toggleHoverLayerFlag(true); - } - - var mergedState = this._mergeStates(stateObjects); - - var animationCfg = this.stateTransition; - this.saveCurrentToNormalState(mergedState); - - this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); - - var textContent = this._textContent; - var textGuide = this._textGuide; - - if (textContent) { - textContent.useStates(states, noAnimation, useHoverLayer); - } - - if (textGuide) { - textGuide.useStates(states, noAnimation, useHoverLayer); - } - - this._updateAnimationTargets(); - - this.currentStates = states.slice(); - this.markRedraw(); - - if (!useHoverLayer && this.__inHover) { - this._toggleHoverLayerFlag(false); - - this.__dirty &= ~REDRAW_BIT; - } - } - }; - - Element.prototype.isSilent = function () { - var isSilent = this.silent; - var ancestor = this.parent; - - while (!isSilent && ancestor) { - if (ancestor.silent) { - isSilent = true; - break; - } - - ancestor = ancestor.parent; - } - - return isSilent; - }; - - Element.prototype._updateAnimationTargets = function () { - for (var i = 0; i < this.animators.length; i++) { - var animator = this.animators[i]; - - if (animator.targetName) { - animator.changeTarget(this[animator.targetName]); - } - } - }; - - Element.prototype.removeState = function (state) { - var idx = indexOf(this.currentStates, state); - - if (idx >= 0) { - var currentStates = this.currentStates.slice(); - currentStates.splice(idx, 1); - this.useStates(currentStates); - } - }; - - Element.prototype.replaceState = function (oldState, newState, forceAdd) { - var currentStates = this.currentStates.slice(); - var idx = indexOf(currentStates, oldState); - var newStateExists = indexOf(currentStates, newState) >= 0; - - if (idx >= 0) { - if (!newStateExists) { - currentStates[idx] = newState; - } else { - currentStates.splice(idx, 1); - } - } else if (forceAdd && !newStateExists) { - currentStates.push(newState); - } - - this.useStates(currentStates); - }; - - Element.prototype.toggleState = function (state, enable) { - if (enable) { - this.useState(state, true); - } else { - this.removeState(state); - } - }; - - Element.prototype._mergeStates = function (states) { - var mergedState = {}; - var mergedTextConfig; - - for (var i = 0; i < states.length; i++) { - var state = states[i]; - extend(mergedState, state); - - if (state.textConfig) { - mergedTextConfig = mergedTextConfig || {}; - extend(mergedTextConfig, state.textConfig); - } - } - - if (mergedTextConfig) { - mergedState.textConfig = mergedTextConfig; - } - - return mergedState; - }; - - Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { - var needsRestoreToNormal = !(state && keepCurrentStates); - - if (state && state.textConfig) { - this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig); - extend(this.textConfig, state.textConfig); - } else if (needsRestoreToNormal) { - if (normalState.textConfig) { - this.textConfig = normalState.textConfig; - } - } - - var transitionTarget = {}; - var hasTransition = false; - - for (var i = 0; i < PRIMARY_STATES_KEYS$1.length; i++) { - var key = PRIMARY_STATES_KEYS$1[i]; - var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key]; - - if (state && state[key] != null) { - if (propNeedsTransition) { - hasTransition = true; - transitionTarget[key] = state[key]; - } else { - this[key] = state[key]; - } - } else if (needsRestoreToNormal) { - if (normalState[key] != null) { - if (propNeedsTransition) { - hasTransition = true; - transitionTarget[key] = normalState[key]; - } else { - this[key] = normalState[key]; - } - } - } - } - - if (!transition) { - for (var i = 0; i < this.animators.length; i++) { - var animator = this.animators[i]; - var targetName = animator.targetName; - - if (!animator.getLoop()) { - animator.__changeFinalValue(targetName ? (state || normalState)[targetName] : state || normalState); - } - } - } - - if (hasTransition) { - this._transitionState(stateName, transitionTarget, animationCfg); - } - }; - - Element.prototype._attachComponent = function (componentEl) { - if (componentEl.__zr && !componentEl.__hostTarget) { - { - throw new Error('Text element has been added to zrender.'); - } - } - - if (componentEl === this) { - { - throw new Error('Recursive component attachment.'); - } - } - - var zr = this.__zr; - - if (zr) { - componentEl.addSelfToZr(zr); - } - - componentEl.__zr = zr; - componentEl.__hostTarget = this; - }; - - Element.prototype._detachComponent = function (componentEl) { - if (componentEl.__zr) { - componentEl.removeSelfFromZr(componentEl.__zr); - } - - componentEl.__zr = null; - componentEl.__hostTarget = null; - }; - - Element.prototype.getClipPath = function () { - return this._clipPath; - }; - - Element.prototype.setClipPath = function (clipPath) { - if (this._clipPath && this._clipPath !== clipPath) { - this.removeClipPath(); - } - - this._attachComponent(clipPath); - - this._clipPath = clipPath; - this.markRedraw(); - }; - - Element.prototype.removeClipPath = function () { - var clipPath = this._clipPath; - - if (clipPath) { - this._detachComponent(clipPath); - - this._clipPath = null; - this.markRedraw(); - } - }; - - Element.prototype.getTextContent = function () { - return this._textContent; - }; - - Element.prototype.setTextContent = function (textEl) { - var previousTextContent = this._textContent; - - if (previousTextContent === textEl) { - return; - } - - if (previousTextContent && previousTextContent !== textEl) { - this.removeTextContent(); - } - - { - if (textEl.__zr && !textEl.__hostTarget) { - throw new Error('Text element has been added to zrender.'); - } - } - textEl.innerTransformable = new Transformable(); - - this._attachComponent(textEl); - - this._textContent = textEl; - this.markRedraw(); - }; - - Element.prototype.setTextConfig = function (cfg) { - if (!this.textConfig) { - this.textConfig = {}; - } - - extend(this.textConfig, cfg); - this.markRedraw(); - }; - - Element.prototype.removeTextConfig = function () { - this.textConfig = null; - this.markRedraw(); - }; - - Element.prototype.removeTextContent = function () { - var textEl = this._textContent; - - if (textEl) { - textEl.innerTransformable = null; - - this._detachComponent(textEl); - - this._textContent = null; - this._innerTextDefaultStyle = null; - this.markRedraw(); - } - }; - - Element.prototype.getTextGuideLine = function () { - return this._textGuide; - }; - - Element.prototype.setTextGuideLine = function (guideLine) { - if (this._textGuide && this._textGuide !== guideLine) { - this.removeTextGuideLine(); - } - - this._attachComponent(guideLine); - - this._textGuide = guideLine; - this.markRedraw(); - }; - - Element.prototype.removeTextGuideLine = function () { - var textGuide = this._textGuide; - - if (textGuide) { - this._detachComponent(textGuide); - - this._textGuide = null; - this.markRedraw(); - } - }; - - Element.prototype.markRedraw = function () { - this.__dirty |= REDRAW_BIT; - var zr = this.__zr; - - if (zr) { - if (this.__inHover) { - zr.refreshHover(); - } else { - zr.refresh(); - } - } - - if (this.__hostTarget) { - this.__hostTarget.markRedraw(); - } - }; - - Element.prototype.dirty = function () { - this.markRedraw(); - }; - - Element.prototype._toggleHoverLayerFlag = function (inHover) { - this.__inHover = inHover; - var textContent = this._textContent; - var textGuide = this._textGuide; - - if (textContent) { - textContent.__inHover = inHover; - } - - if (textGuide) { - textGuide.__inHover = inHover; - } - }; - - Element.prototype.addSelfToZr = function (zr) { - if (this.__zr === zr) { - return; - } - - this.__zr = zr; - var animators = this.animators; - - if (animators) { - for (var i = 0; i < animators.length; i++) { - zr.animation.addAnimator(animators[i]); - } - } - - if (this._clipPath) { - this._clipPath.addSelfToZr(zr); - } - - if (this._textContent) { - this._textContent.addSelfToZr(zr); - } - - if (this._textGuide) { - this._textGuide.addSelfToZr(zr); - } - }; - - Element.prototype.removeSelfFromZr = function (zr) { - if (!this.__zr) { - return; - } - - this.__zr = null; - var animators = this.animators; - - if (animators) { - for (var i = 0; i < animators.length; i++) { - zr.animation.removeAnimator(animators[i]); - } - } - - if (this._clipPath) { - this._clipPath.removeSelfFromZr(zr); - } - - if (this._textContent) { - this._textContent.removeSelfFromZr(zr); - } - - if (this._textGuide) { - this._textGuide.removeSelfFromZr(zr); - } - }; - - Element.prototype.animate = function (key, loop, allowDiscreteAnimation) { - var target = key ? this[key] : this; - { - if (!target) { - logError('Property "' + key + '" is not existed in element ' + this.id); - return; - } - } - var animator = new Animator(target, loop, allowDiscreteAnimation); - key && (animator.targetName = key); - this.addAnimator(animator, key); - return animator; - }; - - Element.prototype.addAnimator = function (animator, key) { - var zr = this.__zr; - var el = this; - animator.during(function () { - el.updateDuringAnimation(key); - }).done(function () { - var animators = el.animators; - var idx = indexOf(animators, animator); - - if (idx >= 0) { - animators.splice(idx, 1); - } - }); - this.animators.push(animator); - - if (zr) { - zr.animation.addAnimator(animator); - } - - zr && zr.wakeUp(); - }; - - Element.prototype.updateDuringAnimation = function (key) { - this.markRedraw(); - }; - - Element.prototype.stopAnimation = function (scope, forwardToLast) { - var animators = this.animators; - var len = animators.length; - var leftAnimators = []; - - for (var i = 0; i < len; i++) { - var animator = animators[i]; - - if (!scope || scope === animator.scope) { - animator.stop(forwardToLast); - } else { - leftAnimators.push(animator); - } - } - - this.animators = leftAnimators; - return this; - }; - - Element.prototype.animateTo = function (target, cfg, animationProps) { - animateTo(this, target, cfg, animationProps); - }; - - Element.prototype.animateFrom = function (target, cfg, animationProps) { - animateTo(this, target, cfg, animationProps, true); - }; - - Element.prototype._transitionState = function (stateName, target, cfg, animationProps) { - var animators = animateTo(this, target, cfg, animationProps); - - for (var i = 0; i < animators.length; i++) { - animators[i].__fromStateTransition = stateName; - } - }; - - Element.prototype.getBoundingRect = function () { - return null; - }; - - Element.prototype.getPaintRect = function () { - return null; - }; - - Element.initDefaultProps = function () { - var elProto = Element.prototype; - elProto.type = 'element'; - elProto.name = ''; - elProto.ignore = elProto.silent = elProto.isGroup = elProto.draggable = elProto.dragging = elProto.ignoreClip = elProto.__inHover = false; - elProto.__dirty = REDRAW_BIT; - var logs = {}; - - function logDeprecatedError(key, xKey, yKey) { - if (!logs[key + xKey + yKey]) { - console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead"); - logs[key + xKey + yKey] = true; - } - } - - function createLegacyProperty(key, privateKey, xKey, yKey) { - Object.defineProperty(elProto, key, { - get: function () { - { - logDeprecatedError(key, xKey, yKey); - } - - if (!this[privateKey]) { - var pos = this[privateKey] = []; - enhanceArray(this, pos); - } - - return this[privateKey]; - }, - set: function (pos) { - { - logDeprecatedError(key, xKey, yKey); - } - this[xKey] = pos[0]; - this[yKey] = pos[1]; - this[privateKey] = pos; - enhanceArray(this, pos); - } - }); - - function enhanceArray(self, pos) { - Object.defineProperty(pos, 0, { - get: function () { - return self[xKey]; - }, - set: function (val) { - self[xKey] = val; - } - }); - Object.defineProperty(pos, 1, { - get: function () { - return self[yKey]; - }, - set: function (val) { - self[yKey] = val; - } - }); - } - } - - if (Object.defineProperty) { - createLegacyProperty('position', '_legacyPos', 'x', 'y'); - createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY'); - createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY'); - } - }(); - - return Element; - }(); - - mixin(Element, Eventful); - mixin(Element, Transformable); - - function animateTo(animatable, target, cfg, animationProps, reverse) { - cfg = cfg || {}; - var animators = []; - animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse); - var finishCount = animators.length; - var doneHappened = false; - var cfgDone = cfg.done; - var cfgAborted = cfg.aborted; - - var doneCb = function () { - doneHappened = true; - finishCount--; - - if (finishCount <= 0) { - doneHappened ? cfgDone && cfgDone() : cfgAborted && cfgAborted(); - } - }; - - var abortedCb = function () { - finishCount--; - - if (finishCount <= 0) { - doneHappened ? cfgDone && cfgDone() : cfgAborted && cfgAborted(); - } - }; - - if (!finishCount) { - cfgDone && cfgDone(); - } - - if (animators.length > 0 && cfg.during) { - animators[0].during(function (target, percent) { - cfg.during(percent); - }); - } - - for (var i = 0; i < animators.length; i++) { - var animator = animators[i]; - - if (doneCb) { - animator.done(doneCb); - } - - if (abortedCb) { - animator.aborted(abortedCb); - } - - if (cfg.force) { - animator.duration(cfg.duration); - } - - animator.start(cfg.easing); - } - - return animators; - } - - function copyArrShallow(source, target, len) { - for (var i = 0; i < len; i++) { - source[i] = target[i]; - } - } - - function is2DArray(value) { - return isArrayLike(value[0]); - } - - function copyValue(target, source, key) { - if (isArrayLike(source[key])) { - if (!isArrayLike(target[key])) { - target[key] = []; - } - - if (isTypedArray(source[key])) { - var len = source[key].length; - - if (target[key].length !== len) { - target[key] = new source[key].constructor(len); - copyArrShallow(target[key], source[key], len); - } - } else { - var sourceArr = source[key]; - var targetArr = target[key]; - var len0 = sourceArr.length; - - if (is2DArray(sourceArr)) { - var len1 = sourceArr[0].length; - - for (var i = 0; i < len0; i++) { - if (!targetArr[i]) { - targetArr[i] = Array.prototype.slice.call(sourceArr[i]); - } else { - copyArrShallow(targetArr[i], sourceArr[i], len1); - } - } - } else { - copyArrShallow(targetArr, sourceArr, len0); - } - - targetArr.length = sourceArr.length; - } - } else { - target[key] = source[key]; - } - } - - function isValueSame(val1, val2) { - return val1 === val2 || isArrayLike(val1) && isArrayLike(val2) && is1DArraySame(val1, val2); - } - - function is1DArraySame(arr0, arr1) { - var len = arr0.length; - - if (len !== arr1.length) { - return false; - } - - for (var i = 0; i < len; i++) { - if (arr0[i] !== arr1[i]) { - return false; - } - } - - return true; - } - - function animateToShallow(animatable, topKey, animateObj, target, cfg, animationProps, animators, reverse) { - var targetKeys = keys(target); - var duration = cfg.duration; - var delay = cfg.delay; - var additive = cfg.additive; - var setToFinal = cfg.setToFinal; - var animateAll = !isObject$2(animationProps); - var existsAnimators = animatable.animators; - var animationKeys = []; - - for (var k = 0; k < targetKeys.length; k++) { - var innerKey = targetKeys[k]; - var targetVal = target[innerKey]; - - if (targetVal != null && animateObj[innerKey] != null && (animateAll || animationProps[innerKey])) { - if (isObject$2(targetVal) && !isArrayLike(targetVal) && !isGradientObject(targetVal)) { - if (topKey) { - if (!reverse) { - animateObj[innerKey] = targetVal; - animatable.updateDuringAnimation(topKey); - } - - continue; - } - - animateToShallow(animatable, innerKey, animateObj[innerKey], targetVal, cfg, animationProps && animationProps[innerKey], animators, reverse); - } else { - animationKeys.push(innerKey); - } - } else if (!reverse) { - animateObj[innerKey] = targetVal; - animatable.updateDuringAnimation(topKey); - animationKeys.push(innerKey); - } - } - - var keyLen = animationKeys.length; - - if (!additive && keyLen) { - for (var i = 0; i < existsAnimators.length; i++) { - var animator = existsAnimators[i]; - - if (animator.targetName === topKey) { - var allAborted = animator.stopTracks(animationKeys); - - if (allAborted) { - var idx = indexOf(existsAnimators, animator); - existsAnimators.splice(idx, 1); - } - } - } - } - - if (!cfg.force) { - animationKeys = filter(animationKeys, function (key) { - return !isValueSame(target[key], animateObj[key]); - }); - keyLen = animationKeys.length; - } - - if (keyLen > 0 || cfg.force && !animators.length) { - var revertedSource = void 0; - var reversedTarget = void 0; - var sourceClone = void 0; - - if (reverse) { - reversedTarget = {}; - - if (setToFinal) { - revertedSource = {}; - } - - for (var i = 0; i < keyLen; i++) { - var innerKey = animationKeys[i]; - reversedTarget[innerKey] = animateObj[innerKey]; - - if (setToFinal) { - revertedSource[innerKey] = target[innerKey]; - } else { - animateObj[innerKey] = target[innerKey]; - } - } - } else if (setToFinal) { - sourceClone = {}; - - for (var i = 0; i < keyLen; i++) { - var innerKey = animationKeys[i]; - sourceClone[innerKey] = cloneValue(animateObj[innerKey]); - copyValue(animateObj, target, innerKey); - } - } - - var animator = new Animator(animateObj, false, false, additive ? filter(existsAnimators, function (animator) { - return animator.targetName === topKey; - }) : null); - animator.targetName = topKey; - - if (cfg.scope) { - animator.scope = cfg.scope; - } - - if (setToFinal && revertedSource) { - animator.whenWithKeys(0, revertedSource, animationKeys); - } - - if (sourceClone) { - animator.whenWithKeys(0, sourceClone, animationKeys); - } - - animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animationKeys).delay(delay || 0); - animatable.addAnimator(animator, topKey); - animators.push(animator); - } - } - - var Group$2 = function (_super) { - __extends(Group, _super); - - function Group(opts) { - var _this = _super.call(this) || this; - - _this.isGroup = true; - _this._children = []; - - _this.attr(opts); - - return _this; - } - - Group.prototype.childrenRef = function () { - return this._children; - }; - - Group.prototype.children = function () { - return this._children.slice(); - }; - - Group.prototype.childAt = function (idx) { - return this._children[idx]; - }; - - Group.prototype.childOfName = function (name) { - var children = this._children; - - for (var i = 0; i < children.length; i++) { - if (children[i].name === name) { - return children[i]; - } - } - }; - - Group.prototype.childCount = function () { - return this._children.length; - }; - - Group.prototype.add = function (child) { - if (child) { - if (child !== this && child.parent !== this) { - this._children.push(child); - - this._doAdd(child); - } - - { - if (child.__hostTarget) { - throw 'This elemenet has been used as an attachment'; - } - } - } - - return this; - }; - - Group.prototype.addBefore = function (child, nextSibling) { - if (child && child !== this && child.parent !== this && nextSibling && nextSibling.parent === this) { - var children = this._children; - var idx = children.indexOf(nextSibling); - - if (idx >= 0) { - children.splice(idx, 0, child); - - this._doAdd(child); - } - } - - return this; - }; - - Group.prototype.replace = function (oldChild, newChild) { - var idx = indexOf(this._children, oldChild); - - if (idx >= 0) { - this.replaceAt(newChild, idx); - } - - return this; - }; - - Group.prototype.replaceAt = function (child, index) { - var children = this._children; - var old = children[index]; - - if (child && child !== this && child.parent !== this && child !== old) { - children[index] = child; - old.parent = null; - var zr = this.__zr; - - if (zr) { - old.removeSelfFromZr(zr); - } - - this._doAdd(child); - } - - return this; - }; - - Group.prototype._doAdd = function (child) { - if (child.parent) { - child.parent.remove(child); - } - - child.parent = this; - var zr = this.__zr; - - if (zr && zr !== child.__zr) { - child.addSelfToZr(zr); - } - - zr && zr.refresh(); - }; - - Group.prototype.remove = function (child) { - var zr = this.__zr; - var children = this._children; - var idx = indexOf(children, child); - - if (idx < 0) { - return this; - } - - children.splice(idx, 1); - child.parent = null; - - if (zr) { - child.removeSelfFromZr(zr); - } - - zr && zr.refresh(); - return this; - }; - - Group.prototype.removeAll = function () { - var children = this._children; - var zr = this.__zr; - - for (var i = 0; i < children.length; i++) { - var child = children[i]; - - if (zr) { - child.removeSelfFromZr(zr); - } - - child.parent = null; - } - - children.length = 0; - return this; - }; - - Group.prototype.eachChild = function (cb, context) { - var children = this._children; - - for (var i = 0; i < children.length; i++) { - var child = children[i]; - cb.call(context, child, i); - } - - return this; - }; - - Group.prototype.traverse = function (cb, context) { - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; - var stopped = cb.call(context, child); - - if (child.isGroup && !stopped) { - child.traverse(cb, context); - } - } - - return this; - }; - - Group.prototype.addSelfToZr = function (zr) { - _super.prototype.addSelfToZr.call(this, zr); - - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; - child.addSelfToZr(zr); - } - }; - - Group.prototype.removeSelfFromZr = function (zr) { - _super.prototype.removeSelfFromZr.call(this, zr); - - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; - child.removeSelfFromZr(zr); - } - }; - - Group.prototype.getBoundingRect = function (includeChildren) { - var tmpRect = new BoundingRect(0, 0, 0, 0); - var children = includeChildren || this._children; - var tmpMat = []; - var rect = null; - - for (var i = 0; i < children.length; i++) { - var child = children[i]; - - if (child.ignore || child.invisible) { - continue; - } - - var childRect = child.getBoundingRect(); - var transform = child.getLocalTransform(tmpMat); - - if (transform) { - BoundingRect.applyTransform(tmpRect, childRect, transform); - rect = rect || tmpRect.clone(); - rect.union(tmpRect); - } else { - rect = rect || childRect.clone(); - rect.union(childRect); - } - } - - return rect || tmpRect; - }; - - return Group; - }(Element); - - Group$2.prototype.type = 'group'; - /*! - * ZRender, a high performance 2d drawing library. - * - * Copyright (c) 2013, Baidu Inc. - * All rights reserved. - * - * LICENSE - * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt - */ - - var painterCtors = {}; - var instances$1 = {}; - - function delInstance(id) { - delete instances$1[id]; - } - - function isDarkMode(backgroundColor) { - if (!backgroundColor) { - return false; - } - - if (typeof backgroundColor === 'string') { - return lum(backgroundColor, 1) < DARK_MODE_THRESHOLD; - } else if (backgroundColor.colorStops) { - var colorStops = backgroundColor.colorStops; - var totalLum = 0; - var len = colorStops.length; - - for (var i = 0; i < len; i++) { - totalLum += lum(colorStops[i].color, 1); - } - - totalLum /= len; - return totalLum < DARK_MODE_THRESHOLD; - } - - return false; - } - - var ZRender = function () { - function ZRender(id, dom, opts) { - var _this = this; - - this._sleepAfterStill = 10; - this._stillFrameAccum = 0; - this._needsRefresh = true; - this._needsRefreshHover = true; - this._darkMode = false; - opts = opts || {}; - this.dom = dom; - this.id = id; - var storage = new Storage(); - var rendererType = opts.renderer || 'canvas'; - - if (!painterCtors[rendererType]) { - rendererType = keys(painterCtors)[0]; - } - - { - if (!painterCtors[rendererType]) { - throw new Error("Renderer '" + rendererType + "' is not imported. Please import it first."); - } - } - opts.useDirtyRect = opts.useDirtyRect == null ? false : opts.useDirtyRect; - var painter = new painterCtors[rendererType](dom, storage, opts, id); - var ssrMode = opts.ssr || painter.ssrOnly; - this.storage = storage; - this.painter = painter; - var handlerProxy = !env.node && !env.worker && !ssrMode ? new HandlerDomProxy(painter.getViewportRoot(), painter.root) : null; - var useCoarsePointer = opts.useCoarsePointer; - var usePointerSize = useCoarsePointer == null || useCoarsePointer === 'auto' ? env.touchEventsSupported : !!useCoarsePointer; - var defaultPointerSize = 44; - var pointerSize; - - if (usePointerSize) { - pointerSize = retrieve2(opts.pointerSize, defaultPointerSize); - } - - this.handler = new Handler(storage, painter, handlerProxy, painter.root, pointerSize); - this.animation = new Animation({ - stage: { - update: ssrMode ? null : function () { - return _this._flush(true); - } - } - }); - - if (!ssrMode) { - this.animation.start(); - } - } - - ZRender.prototype.add = function (el) { - if (this._disposed || !el) { - return; - } - - this.storage.addRoot(el); - el.addSelfToZr(this); - this.refresh(); - }; - - ZRender.prototype.remove = function (el) { - if (this._disposed || !el) { - return; - } - - this.storage.delRoot(el); - el.removeSelfFromZr(this); - this.refresh(); - }; - - ZRender.prototype.configLayer = function (zLevel, config) { - if (this._disposed) { - return; - } - - if (this.painter.configLayer) { - this.painter.configLayer(zLevel, config); - } - - this.refresh(); - }; - - ZRender.prototype.setBackgroundColor = function (backgroundColor) { - if (this._disposed) { - return; - } - - if (this.painter.setBackgroundColor) { - this.painter.setBackgroundColor(backgroundColor); - } - - this.refresh(); - this._backgroundColor = backgroundColor; - this._darkMode = isDarkMode(backgroundColor); - }; - - ZRender.prototype.getBackgroundColor = function () { - return this._backgroundColor; - }; - - ZRender.prototype.setDarkMode = function (darkMode) { - this._darkMode = darkMode; - }; - - ZRender.prototype.isDarkMode = function () { - return this._darkMode; - }; - - ZRender.prototype.refreshImmediately = function (fromInside) { - if (this._disposed) { - return; - } - - if (!fromInside) { - this.animation.update(true); - } - - this._needsRefresh = false; - this.painter.refresh(); - this._needsRefresh = false; - }; - - ZRender.prototype.refresh = function () { - if (this._disposed) { - return; - } - - this._needsRefresh = true; - this.animation.start(); - }; - - ZRender.prototype.flush = function () { - if (this._disposed) { - return; - } - - this._flush(false); - }; - - ZRender.prototype._flush = function (fromInside) { - var triggerRendered; - var start = getTime(); - - if (this._needsRefresh) { - triggerRendered = true; - this.refreshImmediately(fromInside); - } - - if (this._needsRefreshHover) { - triggerRendered = true; - this.refreshHoverImmediately(); - } - - var end = getTime(); - - if (triggerRendered) { - this._stillFrameAccum = 0; - this.trigger('rendered', { - elapsedTime: end - start - }); - } else if (this._sleepAfterStill > 0) { - this._stillFrameAccum++; - - if (this._stillFrameAccum > this._sleepAfterStill) { - this.animation.stop(); - } - } - }; - - ZRender.prototype.setSleepAfterStill = function (stillFramesCount) { - this._sleepAfterStill = stillFramesCount; - }; - - ZRender.prototype.wakeUp = function () { - if (this._disposed) { - return; - } - - this.animation.start(); - this._stillFrameAccum = 0; - }; - - ZRender.prototype.refreshHover = function () { - this._needsRefreshHover = true; - }; - - ZRender.prototype.refreshHoverImmediately = function () { - if (this._disposed) { - return; - } - - this._needsRefreshHover = false; - - if (this.painter.refreshHover && this.painter.getType() === 'canvas') { - this.painter.refreshHover(); - } - }; - - ZRender.prototype.resize = function (opts) { - if (this._disposed) { - return; - } - - opts = opts || {}; - this.painter.resize(opts.width, opts.height); - this.handler.resize(); - }; - - ZRender.prototype.clearAnimation = function () { - if (this._disposed) { - return; - } - - this.animation.clear(); - }; - - ZRender.prototype.getWidth = function () { - if (this._disposed) { - return; - } - - return this.painter.getWidth(); - }; - - ZRender.prototype.getHeight = function () { - if (this._disposed) { - return; - } - - return this.painter.getHeight(); - }; - - ZRender.prototype.setCursorStyle = function (cursorStyle) { - if (this._disposed) { - return; - } - - this.handler.setCursorStyle(cursorStyle); - }; - - ZRender.prototype.findHover = function (x, y) { - if (this._disposed) { - return; - } - - return this.handler.findHover(x, y); - }; - - ZRender.prototype.on = function (eventName, eventHandler, context) { - if (!this._disposed) { - this.handler.on(eventName, eventHandler, context); - } - - return this; - }; - - ZRender.prototype.off = function (eventName, eventHandler) { - if (this._disposed) { - return; - } - - this.handler.off(eventName, eventHandler); - }; - - ZRender.prototype.trigger = function (eventName, event) { - if (this._disposed) { - return; - } - - this.handler.trigger(eventName, event); - }; - - ZRender.prototype.clear = function () { - if (this._disposed) { - return; - } - - var roots = this.storage.getRoots(); - - for (var i = 0; i < roots.length; i++) { - if (roots[i] instanceof Group$2) { - roots[i].removeSelfFromZr(this); - } - } - - this.storage.delAllRoots(); - this.painter.clear(); - }; - - ZRender.prototype.dispose = function () { - if (this._disposed) { - return; - } - - this.animation.stop(); - this.clear(); - this.storage.dispose(); - this.painter.dispose(); - this.handler.dispose(); - this.animation = this.storage = this.painter = this.handler = null; - this._disposed = true; - delInstance(this.id); - }; - - return ZRender; - }(); - - function init$1(dom, opts) { - var zr = new ZRender(guid(), dom, opts); - instances$1[zr.id] = zr; - return zr; - } - - function dispose$1(zr) { - zr.dispose(); - } - - function disposeAll() { - for (var key in instances$1) { - if (instances$1.hasOwnProperty(key)) { - instances$1[key].dispose(); - } - } - - instances$1 = {}; - } - - function getInstance(id) { - return instances$1[id]; - } - - function registerPainter(name, Ctor) { - painterCtors[name] = Ctor; - } - - var ssrDataGetter; - - function getElementSSRData(el) { - if (typeof ssrDataGetter === 'function') { - return ssrDataGetter(el); - } - } - - function registerSSRDataGetter(getter) { - ssrDataGetter = getter; - } - - var version$1 = '5.5.0'; - var zrender = /*#__PURE__*/Object.freeze({ - __proto__: null, - dispose: dispose$1, - disposeAll: disposeAll, - getElementSSRData: getElementSSRData, - getInstance: getInstance, - init: init$1, - registerPainter: registerPainter, - registerSSRDataGetter: registerSSRDataGetter, - version: version$1 - }); - var RADIAN_EPSILON = 1e-4; // Although chrome already enlarge this number to 100 for `toFixed`, but - // we sill follow the spec for compatibility. - - var ROUND_SUPPORTED_PRECISION_MAX = 20; - - function _trim(str) { - return str.replace(/^\s+|\s+$/g, ''); - } - /** - * Linear mapping a value from domain to range - * @param val - * @param domain Domain extent domain[0] can be bigger than domain[1] - * @param range Range extent range[0] can be bigger than range[1] - * @param clamp Default to be false - */ - - - function linearMap(val, domain, range, clamp) { - var d0 = domain[0]; - var d1 = domain[1]; - var r0 = range[0]; - var r1 = range[1]; - var subDomain = d1 - d0; - var subRange = r1 - r0; - - if (subDomain === 0) { - return subRange === 0 ? r0 : (r0 + r1) / 2; - } // Avoid accuracy problem in edge, such as - // 146.39 - 62.83 === 83.55999999999999. - // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError - // It is a little verbose for efficiency considering this method - // is a hotspot. - - - if (clamp) { - if (subDomain > 0) { - if (val <= d0) { - return r0; - } else if (val >= d1) { - return r1; - } - } else { - if (val >= d0) { - return r0; - } else if (val <= d1) { - return r1; - } - } - } else { - if (val === d0) { - return r0; - } - - if (val === d1) { - return r1; - } - } - - return (val - d0) / subDomain * subRange + r0; - } - /** - * Convert a percent string to absolute number. - * Returns NaN if percent is not a valid string or number - */ - - - function parsePercent(percent, all) { - switch (percent) { - case 'center': - case 'middle': - percent = '50%'; - break; - - case 'left': - case 'top': - percent = '0%'; - break; - - case 'right': - case 'bottom': - percent = '100%'; - break; - } - - if (isString(percent)) { - if (_trim(percent).match(/%$/)) { - return parseFloat(percent) / 100 * all; - } - - return parseFloat(percent); - } - - return percent == null ? NaN : +percent; - } - - function round$2(x, precision, returnStr) { - if (precision == null) { - precision = 10; - } // Avoid range error - - - precision = Math.min(Math.max(0, precision), ROUND_SUPPORTED_PRECISION_MAX); // PENDING: 1.005.toFixed(2) is '1.00' rather than '1.01' - - x = (+x).toFixed(precision); - return returnStr ? x : +x; - } - /** - * Inplacd asc sort arr. - * The input arr will be modified. - */ - - - function asc(arr) { - arr.sort(function (a, b) { - return a - b; - }); - return arr; - } - /** - * Get precision. - */ - - - function getPrecision(val) { - val = +val; - - if (isNaN(val)) { - return 0; - } // It is much faster than methods converting number to string as follows - // let tmp = val.toString(); - // return tmp.length - 1 - tmp.indexOf('.'); - // especially when precision is low - // Notice: - // (1) If the loop count is over about 20, it is slower than `getPrecisionSafe`. - // (see https://jsbench.me/2vkpcekkvw/1) - // (2) If the val is less than for example 1e-15, the result may be incorrect. - // (see test/ut/spec/util/number.test.ts `getPrecision_equal_random`) - - - if (val > 1e-14) { - var e = 1; - - for (var i = 0; i < 15; i++, e *= 10) { - if (Math.round(val * e) / e === val) { - return i; - } - } - } - - return getPrecisionSafe(val); - } - /** - * Get precision with slow but safe method - */ - - - function getPrecisionSafe(val) { - // toLowerCase for: '3.4E-12' - var str = val.toString().toLowerCase(); // Consider scientific notation: '3.4e-12' '3.4e+12' - - var eIndex = str.indexOf('e'); - var exp = eIndex > 0 ? +str.slice(eIndex + 1) : 0; - var significandPartLen = eIndex > 0 ? eIndex : str.length; - var dotIndex = str.indexOf('.'); - var decimalPartLen = dotIndex < 0 ? 0 : significandPartLen - 1 - dotIndex; - return Math.max(0, decimalPartLen - exp); - } - /** - * Minimal dicernible data precisioin according to a single pixel. - */ - - - function getPixelPrecision(dataExtent, pixelExtent) { - var log = Math.log; - var LN10 = Math.LN10; - var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); - var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); // toFixed() digits argument must be between 0 and 20. - - var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); - return !isFinite(precision) ? 20 : precision; - } - /** - * Get a data of given precision, assuring the sum of percentages - * in valueList is 1. - * The largest remainder method is used. - * https://en.wikipedia.org/wiki/Largest_remainder_method - * - * @param valueList a list of all data - * @param idx index of the data to be processed in valueList - * @param precision integer number showing digits of precision - * @return percent ranging from 0 to 100 - */ - - - function getPercentWithPrecision(valueList, idx, precision) { - if (!valueList[idx]) { - return 0; - } - - var seats = getPercentSeats(valueList, precision); - return seats[idx] || 0; - } - /** - * Get a data of given precision, assuring the sum of percentages - * in valueList is 1. - * The largest remainder method is used. - * https://en.wikipedia.org/wiki/Largest_remainder_method - * - * @param valueList a list of all data - * @param precision integer number showing digits of precision - * @return {Array} - */ - - - function getPercentSeats(valueList, precision) { - var sum = reduce(valueList, function (acc, val) { - return acc + (isNaN(val) ? 0 : val); - }, 0); - - if (sum === 0) { - return []; - } - - var digits = Math.pow(10, precision); - var votesPerQuota = map$1(valueList, function (val) { - return (isNaN(val) ? 0 : val) / sum * digits * 100; - }); - var targetSeats = digits * 100; - var seats = map$1(votesPerQuota, function (votes) { - // Assign automatic seats. - return Math.floor(votes); - }); - var currentSum = reduce(seats, function (acc, val) { - return acc + val; - }, 0); - var remainder = map$1(votesPerQuota, function (votes, idx) { - return votes - seats[idx]; - }); // Has remainding votes. - - while (currentSum < targetSeats) { - // Find next largest remainder. - var max = Number.NEGATIVE_INFINITY; - var maxId = null; - - for (var i = 0, len = remainder.length; i < len; ++i) { - if (remainder[i] > max) { - max = remainder[i]; - maxId = i; - } - } // Add a vote to max remainder. - - - ++seats[maxId]; - remainder[maxId] = 0; - ++currentSum; - } - - return map$1(seats, function (seat) { - return seat / digits; - }); - } - /** - * Solve the floating point adding problem like 0.1 + 0.2 === 0.30000000000000004 - * See - */ - - - function addSafe(val0, val1) { - var maxPrecision = Math.max(getPrecision(val0), getPrecision(val1)); // const multiplier = Math.pow(10, maxPrecision); - // return (Math.round(val0 * multiplier) + Math.round(val1 * multiplier)) / multiplier; - - var sum = val0 + val1; // // PENDING: support more? - - return maxPrecision > ROUND_SUPPORTED_PRECISION_MAX ? sum : round$2(sum, maxPrecision); - } // Number.MAX_SAFE_INTEGER, ie do not support. - - - var MAX_SAFE_INTEGER = 9007199254740991; - /** - * To 0 - 2 * PI, considering negative radian. - */ - - function remRadian(radian) { - var pi2 = Math.PI * 2; - return (radian % pi2 + pi2) % pi2; - } - /** - * @param {type} radian - * @return {boolean} - */ - - - function isRadianAroundZero(val) { - return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; - } // eslint-disable-next-line - - - var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line - - /** - * @param value valid type: number | string | Date, otherwise return `new Date(NaN)` - * These values can be accepted: - * + An instance of Date, represent a time in its own time zone. - * + Or string in a subset of ISO 8601, only including: - * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06', - * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123', - * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00', - * all of which will be treated as local time if time zone is not specified - * (see ). - * + Or other string format, including (all of which will be treated as local time): - * '2012', '2012-3-1', '2012/3/1', '2012/03/01', - * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123' - * + a timestamp, which represent a time in UTC. - * @return date Never be null/undefined. If invalid, return `new Date(NaN)`. - */ - - function parseDate(value) { - if (value instanceof Date) { - return value; - } else if (isString(value)) { - // Different browsers parse date in different way, so we parse it manually. - // Some other issues: - // new Date('1970-01-01') is UTC, - // new Date('1970/01/01') and new Date('1970-1-01') is local. - // See issue #3623 - var match = TIME_REG.exec(value); - - if (!match) { - // return Invalid Date. - return new Date(NaN); - } // Use local time when no timezone offset is specified. - - - if (!match[8]) { - // match[n] can only be string or undefined. - // But take care of '12' + 1 => '121'. - return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0); - } // Timezoneoffset of Javascript Date has considered DST (Daylight Saving Time, - // https://tc39.github.io/ecma262/#sec-daylight-saving-time-adjustment). - // For example, system timezone is set as "Time Zone: America/Toronto", - // then these code will get different result: - // `new Date(1478411999999).getTimezoneOffset(); // get 240` - // `new Date(1478412000000).getTimezoneOffset(); // get 300` - // So we should not use `new Date`, but use `Date.UTC`. - else { - var hour = +match[4] || 0; - - if (match[8].toUpperCase() !== 'Z') { - hour -= +match[8].slice(0, 3); - } - - return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, match[7] ? +match[7].substring(0, 3) : 0)); - } - } else if (value == null) { - return new Date(NaN); - } - - return new Date(Math.round(value)); - } - /** - * Quantity of a number. e.g. 0.1, 1, 10, 100 - * - * @param val - * @return - */ - - - function quantity(val) { - return Math.pow(10, quantityExponent(val)); - } - /** - * Exponent of the quantity of a number - * e.g., 1234 equals to 1.234*10^3, so quantityExponent(1234) is 3 - * - * @param val non-negative value - * @return - */ - - - function quantityExponent(val) { - if (val === 0) { - return 0; - } - - var exp = Math.floor(Math.log(val) / Math.LN10); - /** - * exp is expected to be the rounded-down result of the base-10 log of val. - * But due to the precision loss with Math.log(val), we need to restore it - * using 10^exp to make sure we can get val back from exp. #11249 - */ - - if (val / Math.pow(10, exp) >= 10) { - exp++; - } - - return exp; - } - /** - * find a “nice” number approximately equal to x. Round the number if round = true, - * take ceiling if round = false. The primary observation is that the “nicest” - * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. - * - * See "Nice Numbers for Graph Labels" of Graphic Gems. - * - * @param val Non-negative value. - * @param round - * @return Niced number - */ - - - function nice(val, round) { - var exponent = quantityExponent(val); - var exp10 = Math.pow(10, exponent); - var f = val / exp10; // 1 <= f < 10 - - var nf; - - if (round) { - if (f < 1.5) { - nf = 1; - } else if (f < 2.5) { - nf = 2; - } else if (f < 4) { - nf = 3; - } else if (f < 7) { - nf = 5; - } else { - nf = 10; - } - } else { - if (f < 1) { - nf = 1; - } else if (f < 2) { - nf = 2; - } else if (f < 3) { - nf = 3; - } else if (f < 5) { - nf = 5; - } else { - nf = 10; - } - } - - val = nf * exp10; // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754). - // 20 is the uppper bound of toFixed. - - return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; - } - /** - * This code was copied from "d3.js" - * . - * See the license statement at the head of this file. - * @param ascArr - */ - - - function quantile(ascArr, p) { - var H = (ascArr.length - 1) * p + 1; - var h = Math.floor(H); - var v = +ascArr[h - 1]; - var e = H - h; - return e ? v + e * (ascArr[h] - v) : v; - } - /** - * Order intervals asc, and split them when overlap. - * expect(numberUtil.reformIntervals([ - * {interval: [18, 62], close: [1, 1]}, - * {interval: [-Infinity, -70], close: [0, 0]}, - * {interval: [-70, -26], close: [1, 1]}, - * {interval: [-26, 18], close: [1, 1]}, - * {interval: [62, 150], close: [1, 1]}, - * {interval: [106, 150], close: [1, 1]}, - * {interval: [150, Infinity], close: [0, 0]} - * ])).toEqual([ - * {interval: [-Infinity, -70], close: [0, 0]}, - * {interval: [-70, -26], close: [1, 1]}, - * {interval: [-26, 18], close: [0, 1]}, - * {interval: [18, 62], close: [0, 1]}, - * {interval: [62, 150], close: [0, 1]}, - * {interval: [150, Infinity], close: [0, 0]} - * ]); - * @param list, where `close` mean open or close - * of the interval, and Infinity can be used. - * @return The origin list, which has been reformed. - */ - - - function reformIntervals(list) { - list.sort(function (a, b) { - return littleThan(a, b, 0) ? -1 : 1; - }); - var curr = -Infinity; - var currClose = 1; - - for (var i = 0; i < list.length;) { - var interval = list[i].interval; - var close_1 = list[i].close; - - for (var lg = 0; lg < 2; lg++) { - if (interval[lg] <= curr) { - interval[lg] = curr; - close_1[lg] = !lg ? 1 - currClose : 1; - } - - curr = interval[lg]; - currClose = close_1[lg]; - } - - if (interval[0] === interval[1] && close_1[0] * close_1[1] !== 1) { - list.splice(i, 1); - } else { - i++; - } - } - - return list; - - function littleThan(a, b, lg) { - return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1)); - } - } - /** - * [Numeric is defined as]: - * `parseFloat(val) == val` - * For example: - * numeric: - * typeof number except NaN, '-123', '123', '2e3', '-2e3', '011', 'Infinity', Infinity, - * and they rounded by white-spaces or line-terminal like ' -123 \n ' (see es spec) - * not-numeric: - * null, undefined, [], {}, true, false, 'NaN', NaN, '123ab', - * empty string, string with only white-spaces or line-terminal (see es spec), - * 0x12, '0x12', '-0x12', 012, '012', '-012', - * non-string, ... - * - * @test See full test cases in `test/ut/spec/util/number.js`. - * @return Must be a typeof number. If not numeric, return NaN. - */ - - - function numericToNumber(val) { - var valFloat = parseFloat(val); - return valFloat == val // eslint-disable-line eqeqeq - && (valFloat !== 0 || !isString(val) || val.indexOf('x') <= 0) // For case ' 0x0 '. - ? valFloat : NaN; - } - /** - * Definition of "numeric": see `numericToNumber`. - */ - - - function isNumeric(val) { - return !isNaN(numericToNumber(val)); - } - /** - * Use random base to prevent users hard code depending on - * this auto generated marker id. - * @return An positive integer. - */ - - - function getRandomIdBase() { - return Math.round(Math.random() * 9); - } - /** - * Get the greatest common divisor. - * - * @param {number} a one number - * @param {number} b the other number - */ - - - function getGreatestCommonDividor(a, b) { - if (b === 0) { - return a; - } - - return getGreatestCommonDividor(b, a % b); - } - /** - * Get the least common multiple. - * - * @param {number} a one number - * @param {number} b the other number - */ - - - function getLeastCommonMultiple(a, b) { - if (a == null) { - return b; - } - - if (b == null) { - return a; - } - - return a * b / getGreatestCommonDividor(a, b); - } - - var ECHARTS_PREFIX = '[ECharts] '; - var storedLogs = {}; - var hasConsole = typeof console !== 'undefined' // eslint-disable-next-line - && console.warn && console.log; - - function outputLog(type, str, onlyOnce) { - if (hasConsole) { - if (onlyOnce) { - if (storedLogs[str]) { - return; - } - - storedLogs[str] = true; - } // eslint-disable-next-line - - - console[type](ECHARTS_PREFIX + str); - } - } - - function log(str, onlyOnce) { - outputLog('log', str, onlyOnce); - } - - function warn(str, onlyOnce) { - outputLog('warn', str, onlyOnce); - } - - function error(str, onlyOnce) { - outputLog('error', str, onlyOnce); - } - - function deprecateLog(str) { - { - // Not display duplicate message. - outputLog('warn', 'DEPRECATED: ' + str, true); - } - } - - function deprecateReplaceLog(oldOpt, newOpt, scope) { - { - deprecateLog((scope ? "[" + scope + "]" : '') + (oldOpt + " is deprecated, use " + newOpt + " instead.")); - } - } - /** - * If in __DEV__ environment, get console printable message for users hint. - * Parameters are separated by ' '. - * @usage - * makePrintable('This is an error on', someVar, someObj); - * - * @param hintInfo anything about the current execution context to hint users. - * @throws Error - */ - - - function makePrintable() { - var hintInfo = []; - - for (var _i = 0; _i < arguments.length; _i++) { - hintInfo[_i] = arguments[_i]; - } - - var msg = ''; - { - // Fuzzy stringify for print. - // This code only exist in dev environment. - var makePrintableStringIfPossible_1 = function (val) { - return val === void 0 ? 'undefined' : val === Infinity ? 'Infinity' : val === -Infinity ? '-Infinity' : eqNaN(val) ? 'NaN' : val instanceof Date ? 'Date(' + val.toISOString() + ')' : isFunction(val) ? 'function () { ... }' : isRegExp(val) ? val + '' : null; - }; - - msg = map$1(hintInfo, function (arg) { - if (isString(arg)) { - // Print without quotation mark for some statement. - return arg; - } else { - var printableStr = makePrintableStringIfPossible_1(arg); - - if (printableStr != null) { - return printableStr; - } else if (typeof JSON !== 'undefined' && JSON.stringify) { - try { - return JSON.stringify(arg, function (n, val) { - var printableStr = makePrintableStringIfPossible_1(val); - return printableStr == null ? val : printableStr; - }); // In most cases the info object is small, so do not line break. - } catch (err) { - return '?'; - } - } else { - return '?'; - } - } - }).join(' '); - } - return msg; - } - /** - * @throws Error - */ - - - function throwError(msg) { - throw new Error(msg); - } - - function interpolateNumber(p0, p1, percent) { - return (p1 - p0) * percent + p0; - } - /** - * Make the name displayable. But we should - * make sure it is not duplicated with user - * specified name, so use '\0'; - */ - - - var DUMMY_COMPONENT_NAME_PREFIX = 'series\0'; - var INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0'; - /** - * If value is not array, then translate it to array. - * @param {*} value - * @return {Array} [value] or value - */ - - function normalizeToArray(value) { - return value instanceof Array ? value : value == null ? [] : [value]; - } - /** - * Sync default option between normal and emphasis like `position` and `show` - * In case some one will write code like - * label: { - * show: false, - * position: 'outside', - * fontSize: 18 - * }, - * emphasis: { - * label: { show: true } - * } - */ - - - function defaultEmphasis(opt, key, subOpts) { - // Caution: performance sensitive. - if (opt) { - opt[key] = opt[key] || {}; - opt.emphasis = opt.emphasis || {}; - opt.emphasis[key] = opt.emphasis[key] || {}; // Default emphasis option from normal - - for (var i = 0, len = subOpts.length; i < len; i++) { - var subOptName = subOpts[i]; - - if (!opt.emphasis[key].hasOwnProperty(subOptName) && opt[key].hasOwnProperty(subOptName)) { - opt.emphasis[key][subOptName] = opt[key][subOptName]; - } - } - } - } - - var TEXT_STYLE_OPTIONS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding']; // modelUtil.LABEL_OPTIONS = modelUtil.TEXT_STYLE_OPTIONS.concat([ - // 'position', 'offset', 'rotate', 'origin', 'show', 'distance', 'formatter', - // 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily', - // // FIXME: deprecated, check and remove it. - // 'textStyle' - // ]); - - /** - * The method does not ensure performance. - * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] - * This helper method retrieves value from data. - */ - - function getDataItemValue(dataItem) { - return isObject$2(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date) ? dataItem.value : dataItem; - } - /** - * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}] - * This helper method determine if dataItem has extra option besides value - */ - - - function isDataItemOption(dataItem) { - return isObject$2(dataItem) && !(dataItem instanceof Array); // // markLine data can be array - // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array)); - } - /** - * Mapping to existings for merge. - * - * Mode "normalMege": - * The mapping result (merge result) will keep the order of the existing - * component, rather than the order of new option. Because we should ensure - * some specified index reference (like xAxisIndex) keep work. - * And in most cases, "merge option" is used to update partial option but not - * be expected to change the order. - * - * Mode "replaceMege": - * (1) Only the id mapped components will be merged. - * (2) Other existing components (except internal components) will be removed. - * (3) Other new options will be used to create new component. - * (4) The index of the existing components will not be modified. - * That means their might be "hole" after the removal. - * The new components are created first at those available index. - * - * Mode "replaceAll": - * This mode try to support that reproduce an echarts instance from another - * echarts instance (via `getOption`) in some simple cases. - * In this scenario, the `result` index are exactly the consistent with the `newCmptOptions`, - * which ensures the component index referring (like `xAxisIndex: ?`) corrent. That is, - * the "hole" in `newCmptOptions` will also be kept. - * On the contrary, other modes try best to eliminate holes. - * PENDING: This is an experimental mode yet. - * - * @return See the comment of . - */ - - - function mappingToExists(existings, newCmptOptions, mode) { - var isNormalMergeMode = mode === 'normalMerge'; - var isReplaceMergeMode = mode === 'replaceMerge'; - var isReplaceAllMode = mode === 'replaceAll'; - existings = existings || []; - newCmptOptions = (newCmptOptions || []).slice(); - var existingIdIdxMap = createHashMap(); // Validate id and name on user input option. - - each$4(newCmptOptions, function (cmptOption, index) { - if (!isObject$2(cmptOption)) { - newCmptOptions[index] = null; - return; - } - - { - // There is some legacy case that name is set as `false`. - // But should work normally rather than throw error. - if (cmptOption.id != null && !isValidIdOrName(cmptOption.id)) { - warnInvalidateIdOrName(cmptOption.id); - } - - if (cmptOption.name != null && !isValidIdOrName(cmptOption.name)) { - warnInvalidateIdOrName(cmptOption.name); - } - } - }); - var result = prepareResult(existings, existingIdIdxMap, mode); - - if (isNormalMergeMode || isReplaceMergeMode) { - mappingById(result, existings, existingIdIdxMap, newCmptOptions); - } - - if (isNormalMergeMode) { - mappingByName(result, newCmptOptions); - } - - if (isNormalMergeMode || isReplaceMergeMode) { - mappingByIndex(result, newCmptOptions, isReplaceMergeMode); - } else if (isReplaceAllMode) { - mappingInReplaceAllMode(result, newCmptOptions); - } - - makeIdAndName(result); // The array `result` MUST NOT contain elided items, otherwise the - // forEach will omit those items and result in incorrect result. - - return result; - } - - function prepareResult(existings, existingIdIdxMap, mode) { - var result = []; - - if (mode === 'replaceAll') { - return result; - } // Do not use native `map` to in case that the array `existings` - // contains elided items, which will be omitted. - - - for (var index = 0; index < existings.length; index++) { - var existing = existings[index]; // Because of replaceMerge, `existing` may be null/undefined. - - if (existing && existing.id != null) { - existingIdIdxMap.set(existing.id, index); - } // For non-internal-componnets: - // Mode "normalMerge": all existings kept. - // Mode "replaceMerge": all existing removed unless mapped by id. - // For internal-components: - // go with "replaceMerge" approach in both mode. - - - result.push({ - existing: mode === 'replaceMerge' || isComponentIdInternal(existing) ? null : existing, - newOption: null, - keyInfo: null, - brandNew: null - }); - } - - return result; - } - - function mappingById(result, existings, existingIdIdxMap, newCmptOptions) { - // Mapping by id if specified. - each$4(newCmptOptions, function (cmptOption, index) { - if (!cmptOption || cmptOption.id == null) { - return; - } - - var optionId = makeComparableKey(cmptOption.id); - var existingIdx = existingIdIdxMap.get(optionId); - - if (existingIdx != null) { - var resultItem = result[existingIdx]; - assert(!resultItem.newOption, 'Duplicated option on id "' + optionId + '".'); - resultItem.newOption = cmptOption; // In both mode, if id matched, new option will be merged to - // the existings rather than creating new component model. - - resultItem.existing = existings[existingIdx]; - newCmptOptions[index] = null; - } - }); - } - - function mappingByName(result, newCmptOptions) { - // Mapping by name if specified. - each$4(newCmptOptions, function (cmptOption, index) { - if (!cmptOption || cmptOption.name == null) { - return; - } - - for (var i = 0; i < result.length; i++) { - var existing = result[i].existing; - - if (!result[i].newOption // Consider name: two map to one. - // Can not match when both ids existing but different. - && existing && (existing.id == null || cmptOption.id == null) && !isComponentIdInternal(cmptOption) && !isComponentIdInternal(existing) && keyExistAndEqual('name', existing, cmptOption)) { - result[i].newOption = cmptOption; - newCmptOptions[index] = null; - return; - } - } - }); - } - - function mappingByIndex(result, newCmptOptions, brandNew) { - each$4(newCmptOptions, function (cmptOption) { - if (!cmptOption) { - return; - } // Find the first place that not mapped by id and not internal component (consider the "hole"). - - - var resultItem; - var nextIdx = 0; - - while ( // Be `!resultItem` only when `nextIdx >= result.length`. - (resultItem = result[nextIdx] // (1) Existing models that already have id should be able to mapped to. Because - // after mapping performed, model will always be assigned with an id if user not given. - // After that all models have id. - // (2) If new option has id, it can only set to a hole or append to the last. It should - // not be merged to the existings with different id. Because id should not be overwritten. - // (3) Name can be overwritten, because axis use name as 'show label text'. - ) && (resultItem.newOption || isComponentIdInternal(resultItem.existing) || // In mode "replaceMerge", here no not-mapped-non-internal-existing. - resultItem.existing && cmptOption.id != null && !keyExistAndEqual('id', cmptOption, resultItem.existing))) { - nextIdx++; - } - - if (resultItem) { - resultItem.newOption = cmptOption; - resultItem.brandNew = brandNew; - } else { - result.push({ - newOption: cmptOption, - brandNew: brandNew, - existing: null, - keyInfo: null - }); - } - - nextIdx++; - }); - } - - function mappingInReplaceAllMode(result, newCmptOptions) { - each$4(newCmptOptions, function (cmptOption) { - // The feature "reproduce" requires "hole" will also reproduced - // in case that component index referring are broken. - result.push({ - newOption: cmptOption, - brandNew: true, - existing: null, - keyInfo: null - }); - }); - } - /** - * Make id and name for mapping result (result of mappingToExists) - * into `keyInfo` field. - */ - - - function makeIdAndName(mapResult) { - // We use this id to hash component models and view instances - // in echarts. id can be specified by user, or auto generated. - // The id generation rule ensures new view instance are able - // to mapped to old instance when setOption are called in - // no-merge mode. So we generate model id by name and plus - // type in view id. - // name can be duplicated among components, which is convenient - // to specify multi components (like series) by one name. - // Ensure that each id is distinct. - var idMap = createHashMap(); - each$4(mapResult, function (item) { - var existing = item.existing; - existing && idMap.set(existing.id, item); - }); - each$4(mapResult, function (item) { - var opt = item.newOption; // Force ensure id not duplicated. - - assert(!opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, 'id duplicates: ' + (opt && opt.id)); - opt && opt.id != null && idMap.set(opt.id, item); - !item.keyInfo && (item.keyInfo = {}); - }); // Make name and id. - - each$4(mapResult, function (item, index) { - var existing = item.existing; - var opt = item.newOption; - var keyInfo = item.keyInfo; - - if (!isObject$2(opt)) { - return; - } // Name can be overwritten. Consider case: axis.name = '20km'. - // But id generated by name will not be changed, which affect - // only in that case: setOption with 'not merge mode' and view - // instance will be recreated, which can be accepted. - - - keyInfo.name = opt.name != null ? makeComparableKey(opt.name) : existing ? existing.name // Avoid that different series has the same name, - // because name may be used like in color pallet. - : DUMMY_COMPONENT_NAME_PREFIX + index; - - if (existing) { - keyInfo.id = makeComparableKey(existing.id); - } else if (opt.id != null) { - keyInfo.id = makeComparableKey(opt.id); - } else { - // Consider this situatoin: - // optionA: [{name: 'a'}, {name: 'a'}, {..}] - // optionB [{..}, {name: 'a'}, {name: 'a'}] - // Series with the same name between optionA and optionB - // should be mapped. - var idNum = 0; - - do { - keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++; - } while (idMap.get(keyInfo.id)); - } - - idMap.set(keyInfo.id, item); - }); - } - - function keyExistAndEqual(attr, obj1, obj2) { - var key1 = convertOptionIdName(obj1[attr], null); - var key2 = convertOptionIdName(obj2[attr], null); // See `MappingExistingItem`. `id` and `name` trade string equals to number. - - return key1 != null && key2 != null && key1 === key2; - } - /** - * @return return null if not exist. - */ - - - function makeComparableKey(val) { - { - if (val == null) { - throw new Error(); - } - } - return convertOptionIdName(val, ''); - } - - function convertOptionIdName(idOrName, defaultValue) { - if (idOrName == null) { - return defaultValue; - } - - return isString(idOrName) ? idOrName : isNumber(idOrName) || isStringSafe(idOrName) ? idOrName + '' : defaultValue; - } - - function warnInvalidateIdOrName(idOrName) { - { - warn('`' + idOrName + '` is invalid id or name. Must be a string or number.'); - } - } - - function isValidIdOrName(idOrName) { - return isStringSafe(idOrName) || isNumeric(idOrName); - } - - function isNameSpecified(componentModel) { - var name = componentModel.name; // Is specified when `indexOf` get -1 or > 0. - - return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX)); - } - /** - * @public - * @param {Object} cmptOption - * @return {boolean} - */ - - - function isComponentIdInternal(cmptOption) { - return cmptOption && cmptOption.id != null && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0; - } - - function setComponentTypeToKeyInfo(mappingResult, mainType, componentModelCtor) { - // Set mainType and complete subType. - each$4(mappingResult, function (item) { - var newOption = item.newOption; - - if (isObject$2(newOption)) { - item.keyInfo.mainType = mainType; - item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor); - } - }); - } - - function determineSubType(mainType, newCmptOption, existComponent, componentModelCtor) { - var subType = newCmptOption.type ? newCmptOption.type : existComponent ? existComponent.subType // Use determineSubType only when there is no existComponent. - : componentModelCtor.determineSubType(mainType, newCmptOption); // tooltip, markline, markpoint may always has no subType - - return subType; - } - /** - * @param payload Contains dataIndex (means rawIndex) / dataIndexInside / name - * each of which can be Array or primary type. - * @return dataIndex If not found, return undefined/null. - */ - - - function queryDataIndex(data, payload) { - if (payload.dataIndexInside != null) { - return payload.dataIndexInside; - } else if (payload.dataIndex != null) { - return isArray(payload.dataIndex) ? map$1(payload.dataIndex, function (value) { - return data.indexOfRawIndex(value); - }) : data.indexOfRawIndex(payload.dataIndex); - } else if (payload.name != null) { - return isArray(payload.name) ? map$1(payload.name, function (value) { - return data.indexOfName(value); - }) : data.indexOfName(payload.name); - } - } - /** - * Enable property storage to any host object. - * Notice: Serialization is not supported. - * - * For example: - * let inner = zrUitl.makeInner(); - * - * function some1(hostObj) { - * inner(hostObj).someProperty = 1212; - * ... - * } - * function some2() { - * let fields = inner(this); - * fields.someProperty1 = 1212; - * fields.someProperty2 = 'xx'; - * ... - * } - * - * @return {Function} - */ - - - function makeInner() { - var key = '__ec_inner_' + innerUniqueIndex++; - return function (hostObj) { - return hostObj[key] || (hostObj[key] = {}); - }; - } - - var innerUniqueIndex = getRandomIdBase(); - /** - * The same behavior as `component.getReferringComponents`. - */ - - function parseFinder(ecModel, finderInput, opt) { - var _a = preParseFinder(finderInput, opt), - mainTypeSpecified = _a.mainTypeSpecified, - queryOptionMap = _a.queryOptionMap, - others = _a.others; - - var result = others; - var defaultMainType = opt ? opt.defaultMainType : null; - - if (!mainTypeSpecified && defaultMainType) { - queryOptionMap.set(defaultMainType, {}); - } - - queryOptionMap.each(function (queryOption, mainType) { - var queryResult = queryReferringComponents(ecModel, mainType, queryOption, { - useDefault: defaultMainType === mainType, - enableAll: opt && opt.enableAll != null ? opt.enableAll : true, - enableNone: opt && opt.enableNone != null ? opt.enableNone : true - }); - result[mainType + 'Models'] = queryResult.models; - result[mainType + 'Model'] = queryResult.models[0]; - }); - return result; - } - - function preParseFinder(finderInput, opt) { - var finder; - - if (isString(finderInput)) { - var obj = {}; - obj[finderInput + 'Index'] = 0; - finder = obj; - } else { - finder = finderInput; - } - - var queryOptionMap = createHashMap(); - var others = {}; - var mainTypeSpecified = false; - each$4(finder, function (value, key) { - // Exclude 'dataIndex' and other illgal keys. - if (key === 'dataIndex' || key === 'dataIndexInside') { - others[key] = value; - return; - } - - var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || []; - var mainType = parsedKey[1]; - var queryType = (parsedKey[2] || '').toLowerCase(); - - if (!mainType || !queryType || opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) { - return; - } - - mainTypeSpecified = mainTypeSpecified || !!mainType; - var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {}); - queryOption[queryType] = value; - }); - return { - mainTypeSpecified: mainTypeSpecified, - queryOptionMap: queryOptionMap, - others: others - }; - } - - var SINGLE_REFERRING = { - useDefault: true, - enableAll: false, - enableNone: false - }; - - function queryReferringComponents(ecModel, mainType, userOption, opt) { - opt = opt || SINGLE_REFERRING; - var indexOption = userOption.index; - var idOption = userOption.id; - var nameOption = userOption.name; - var result = { - models: null, - specified: indexOption != null || idOption != null || nameOption != null - }; - - if (!result.specified) { - // Use the first as default if `useDefault`. - var firstCmpt = void 0; - result.models = opt.useDefault && (firstCmpt = ecModel.getComponent(mainType)) ? [firstCmpt] : []; - return result; - } - - if (indexOption === 'none' || indexOption === false) { - assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.'); - result.models = []; - return result; - } // `queryComponents` will return all components if - // both all of index/id/name are null/undefined. - - - if (indexOption === 'all') { - assert(opt.enableAll, '`"all"` is not a valid value on index option.'); - indexOption = idOption = nameOption = null; - } - - result.models = ecModel.queryComponents({ - mainType: mainType, - index: indexOption, - id: idOption, - name: nameOption - }); - return result; - } - - function setAttribute(dom, key, value) { - dom.setAttribute ? dom.setAttribute(key, value) : dom[key] = value; - } - - function getAttribute(dom, key) { - return dom.getAttribute ? dom.getAttribute(key) : dom[key]; - } - - function getTooltipRenderMode(renderModeOption) { - if (renderModeOption === 'auto') { - // Using html when `document` exists, use richText otherwise - return env.domSupported ? 'html' : 'richText'; - } else { - return renderModeOption || 'html'; - } - } - /** - * Interpolate raw values of a series with percent - * - * @param data data - * @param labelModel label model of the text element - * @param sourceValue start value. May be null/undefined when init. - * @param targetValue end value - * @param percent 0~1 percentage; 0 uses start value while 1 uses end value - * @return interpolated values - * If `sourceValue` and `targetValue` are `number`, return `number`. - * If `sourceValue` and `targetValue` are `string`, return `string`. - * If `sourceValue` and `targetValue` are `(string | number)[]`, return `(string | number)[]`. - * Other cases do not supported. - */ - - - function interpolateRawValues(data, precision, sourceValue, targetValue, percent) { - var isAutoPrecision = precision == null || precision === 'auto'; - - if (targetValue == null) { - return targetValue; - } - - if (isNumber(targetValue)) { - var value = interpolateNumber(sourceValue || 0, targetValue, percent); - return round$2(value, isAutoPrecision ? Math.max(getPrecision(sourceValue || 0), getPrecision(targetValue)) : precision); - } else if (isString(targetValue)) { - return percent < 1 ? sourceValue : targetValue; - } else { - var interpolated = []; - var leftArr = sourceValue; - var rightArr = targetValue; - var length_1 = Math.max(leftArr ? leftArr.length : 0, rightArr.length); - - for (var i = 0; i < length_1; ++i) { - var info = data.getDimensionInfo(i); // Don't interpolate ordinal dims - - if (info && info.type === 'ordinal') { - // In init, there is no `sourceValue`, but should better not to get undefined result. - interpolated[i] = (percent < 1 && leftArr ? leftArr : rightArr)[i]; - } else { - var leftVal = leftArr && leftArr[i] ? leftArr[i] : 0; - var rightVal = rightArr[i]; - var value = interpolateNumber(leftVal, rightVal, percent); - interpolated[i] = round$2(value, isAutoPrecision ? Math.max(getPrecision(leftVal), getPrecision(rightVal)) : precision); - } - } - - return interpolated; - } - } - - var TYPE_DELIMITER = '.'; - var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; - var IS_EXTENDED_CLASS = '___EC__EXTENDED_CLASS___'; - /** - * Notice, parseClassType('') should returns {main: '', sub: ''} - * @public - */ - - function parseClassType(componentType) { - var ret = { - main: '', - sub: '' - }; - - if (componentType) { - var typeArr = componentType.split(TYPE_DELIMITER); - ret.main = typeArr[0] || ''; - ret.sub = typeArr[1] || ''; - } - - return ret; - } - /** - * @public - */ - - - function checkClassType(componentType) { - assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal'); - } - - function isExtendedClass(clz) { - return !!(clz && clz[IS_EXTENDED_CLASS]); - } - /** - * Implements `ExtendableConstructor` for `rootClz`. - * - * @usage - * ```ts - * class Xxx {} - * type XxxConstructor = typeof Xxx & ExtendableConstructor - * enableClassExtend(Xxx as XxxConstructor); - * ``` - */ - - - function enableClassExtend(rootClz, mandatoryMethods) { - rootClz.$constructor = rootClz; // FIXME: not necessary? - - rootClz.extend = function (proto) { - { - each$4(mandatoryMethods, function (method) { - if (!proto[method]) { - console.warn('Method `' + method + '` should be implemented' + (proto.type ? ' in ' + proto.type : '') + '.'); - } - }); - } - var superClass = this; - var ExtendedClass; - - if (isESClass(superClass)) { - ExtendedClass = - /** @class */ - function (_super) { - __extends(class_1, _super); - - function class_1() { - return _super.apply(this, arguments) || this; - } - - return class_1; - }(superClass); - } else { - // For backward compat, we both support ts class inheritance and this - // "extend" approach. - // The constructor should keep the same behavior as ts class inheritance: - // If this constructor/$constructor is not declared, auto invoke the super - // constructor. - // If this constructor/$constructor is declared, it is responsible for - // calling the super constructor. - ExtendedClass = function () { - (proto.$constructor || superClass).apply(this, arguments); - }; - - inherits(ExtendedClass, this); - } - - extend(ExtendedClass.prototype, proto); - ExtendedClass[IS_EXTENDED_CLASS] = true; - ExtendedClass.extend = this.extend; - ExtendedClass.superCall = superCall; - ExtendedClass.superApply = superApply; - ExtendedClass.superClass = superClass; - return ExtendedClass; - }; - } - - function isESClass(fn) { - return isFunction(fn) && /^class\s/.test(Function.prototype.toString.call(fn)); - } - /** - * A work around to both support ts extend and this extend mechanism. - * on sub-class. - * @usage - * ```ts - * class Component { ... } - * classUtil.enableClassExtend(Component); - * classUtil.enableClassManagement(Component, {registerWhenExtend: true}); - * - * class Series extends Component { ... } - * // Without calling `markExtend`, `registerWhenExtend` will not work. - * Component.markExtend(Series); - * ``` - */ - - - function mountExtend(SubClz, SupperClz) { - SubClz.extend = SupperClz.extend; - } // A random offset. - - - var classBase = Math.round(Math.random() * 10); - /** - * Implements `CheckableConstructor` for `target`. - * Can not use instanceof, consider different scope by - * cross domain or es module import in ec extensions. - * Mount a method "isInstance()" to Clz. - * - * @usage - * ```ts - * class Xxx {} - * type XxxConstructor = typeof Xxx & CheckableConstructor; - * enableClassCheck(Xxx as XxxConstructor) - * ``` - */ - - function enableClassCheck(target) { - var classAttr = ['__\0is_clz', classBase++].join('_'); - target.prototype[classAttr] = true; - { - assert(!target.isInstance, 'The method "is" can not be defined.'); - } - - target.isInstance = function (obj) { - return !!(obj && obj[classAttr]); - }; - } // superCall should have class info, which can not be fetched from 'this'. - // Consider this case: - // class A has method f, - // class B inherits class A, overrides method f, f call superApply('f'), - // class C inherits class B, does not override method f, - // then when method of class C is called, dead loop occurred. - - - function superCall(context, methodName) { - var args = []; - - for (var _i = 2; _i < arguments.length; _i++) { - args[_i - 2] = arguments[_i]; - } - - return this.superClass.prototype[methodName].apply(context, args); - } - - function superApply(context, methodName, args) { - return this.superClass.prototype[methodName].apply(context, args); - } - /** - * Implements `ClassManager` for `target` - * - * @usage - * ```ts - * class Xxx {} - * type XxxConstructor = typeof Xxx & ClassManager - * enableClassManagement(Xxx as XxxConstructor); - * ``` - */ - - - function enableClassManagement(target) { - /** - * Component model classes - * key: componentType, - * value: - * componentClass, when componentType is 'a' - * or Object., when componentType is 'a.b' - */ - var storage = {}; - - target.registerClass = function (clz) { - // `type` should not be a "instance member". - // If using TS class, should better declared as `static type = 'series.pie'`. - // otherwise users have to mount `type` on prototype manually. - // For backward compat and enable instance visit type via `this.type`, - // we still support fetch `type` from prototype. - var componentFullType = clz.type || clz.prototype.type; - - if (componentFullType) { - checkClassType(componentFullType); // If only static type declared, we assign it to prototype mandatorily. - - clz.prototype.type = componentFullType; - var componentTypeInfo = parseClassType(componentFullType); - - if (!componentTypeInfo.sub) { - { - if (storage[componentTypeInfo.main]) { - console.warn(componentTypeInfo.main + ' exists.'); - } - } - storage[componentTypeInfo.main] = clz; - } else if (componentTypeInfo.sub !== IS_CONTAINER) { - var container = makeContainer(componentTypeInfo); - container[componentTypeInfo.sub] = clz; - } - } - - return clz; - }; - - target.getClass = function (mainType, subType, throwWhenNotFound) { - var clz = storage[mainType]; - - if (clz && clz[IS_CONTAINER]) { - clz = subType ? clz[subType] : null; - } - - if (throwWhenNotFound && !clz) { - throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.'); - } - - return clz; - }; - - target.getClassesByMainType = function (componentType) { - var componentTypeInfo = parseClassType(componentType); - var result = []; - var obj = storage[componentTypeInfo.main]; - - if (obj && obj[IS_CONTAINER]) { - each$4(obj, function (o, type) { - type !== IS_CONTAINER && result.push(o); - }); - } else { - result.push(obj); - } - - return result; - }; - - target.hasClass = function (componentType) { - // Just consider componentType.main. - var componentTypeInfo = parseClassType(componentType); - return !!storage[componentTypeInfo.main]; - }; - /** - * @return Like ['aa', 'bb'], but can not be ['aa.xx'] - */ - - - target.getAllClassMainTypes = function () { - var types = []; - each$4(storage, function (obj, type) { - types.push(type); - }); - return types; - }; - /** - * If a main type is container and has sub types - */ - - - target.hasSubTypes = function (componentType) { - var componentTypeInfo = parseClassType(componentType); - var obj = storage[componentTypeInfo.main]; - return obj && obj[IS_CONTAINER]; - }; - - function makeContainer(componentTypeInfo) { - var container = storage[componentTypeInfo.main]; - - if (!container || !container[IS_CONTAINER]) { - container = storage[componentTypeInfo.main] = {}; - container[IS_CONTAINER] = true; - } - - return container; - } - } // /** - // * @param {string|Array.} properties - // */ - // export function setReadOnly(obj, properties) { - // FIXME It seems broken in IE8 simulation of IE11 - // if (!zrUtil.isArray(properties)) { - // properties = properties != null ? [properties] : []; - // } - // zrUtil.each(properties, function (prop) { - // let value = obj[prop]; - // Object.defineProperty - // && Object.defineProperty(obj, prop, { - // value: value, writable: false - // }); - // zrUtil.isArray(obj[prop]) - // && Object.freeze - // && Object.freeze(obj[prop]); - // }); - // } - - - function makeStyleMapper(properties, ignoreParent) { - // Normalize - for (var i = 0; i < properties.length; i++) { - if (!properties[i][1]) { - properties[i][1] = properties[i][0]; - } - } - - ignoreParent = ignoreParent || false; - return function (model, excludes, includes) { - var style = {}; - - for (var i = 0; i < properties.length; i++) { - var propName = properties[i][1]; - - if (excludes && indexOf(excludes, propName) >= 0 || includes && indexOf(includes, propName) < 0) { - continue; - } - - var val = model.getShallow(propName, ignoreParent); - - if (val != null) { - style[properties[i][0]] = val; - } - } // TODO Text or image? - - - return style; - }; - } - - var AREA_STYLE_KEY_MAP = [['fill', 'color'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['opacity'], ['shadowColor'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. - // So do not transfer decal directly. - ]; - var getAreaStyle = makeStyleMapper(AREA_STYLE_KEY_MAP); - - var AreaStyleMixin = - /** @class */ - function () { - function AreaStyleMixin() {} - - AreaStyleMixin.prototype.getAreaStyle = function (excludes, includes) { - return getAreaStyle(this, excludes, includes); - }; - - return AreaStyleMixin; - }(); - - var globalImageCache = new LRU(50); - - function findExistImage(newImageOrSrc) { - if (typeof newImageOrSrc === 'string') { - var cachedImgObj = globalImageCache.get(newImageOrSrc); - return cachedImgObj && cachedImgObj.image; - } else { - return newImageOrSrc; - } - } - - function createOrUpdateImage(newImageOrSrc, image, hostEl, onload, cbPayload) { - if (!newImageOrSrc) { - return image; - } else if (typeof newImageOrSrc === 'string') { - if (image && image.__zrImageSrc === newImageOrSrc || !hostEl) { - return image; - } - - var cachedImgObj = globalImageCache.get(newImageOrSrc); - var pendingWrap = { - hostEl: hostEl, - cb: onload, - cbPayload: cbPayload - }; - - if (cachedImgObj) { - image = cachedImgObj.image; - !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); - } else { - image = platformApi.loadImage(newImageOrSrc, imageOnLoad, imageOnLoad); - image.__zrImageSrc = newImageOrSrc; - globalImageCache.put(newImageOrSrc, image.__cachedImgObj = { - image: image, - pending: [pendingWrap] - }); - } - - return image; - } else { - return newImageOrSrc; - } - } - - function imageOnLoad() { - var cachedImgObj = this.__cachedImgObj; - this.onload = this.onerror = this.__cachedImgObj = null; - - for (var i = 0; i < cachedImgObj.pending.length; i++) { - var pendingWrap = cachedImgObj.pending[i]; - var cb = pendingWrap.cb; - cb && cb(this, pendingWrap.cbPayload); - pendingWrap.hostEl.dirty(); - } - - cachedImgObj.pending.length = 0; - } - - function isImageReady(image) { - return image && image.width && image.height; - } - - var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; - - function truncateText(text, containerWidth, font, ellipsis, options) { - if (!containerWidth) { - return ''; - } - - var textLines = (text + '').split('\n'); - options = prepareTruncateOptions(containerWidth, font, ellipsis, options); - - for (var i = 0, len = textLines.length; i < len; i++) { - textLines[i] = truncateSingleLine(textLines[i], options); - } - - return textLines.join('\n'); - } - - function prepareTruncateOptions(containerWidth, font, ellipsis, options) { - options = options || {}; - var preparedOpts = extend({}, options); - preparedOpts.font = font; - ellipsis = retrieve2(ellipsis, '...'); - preparedOpts.maxIterations = retrieve2(options.maxIterations, 2); - var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0); - preparedOpts.cnCharWidth = getWidth('国', font); - var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font); - preparedOpts.placeholder = retrieve2(options.placeholder, ''); - var contentWidth = containerWidth = Math.max(0, containerWidth - 1); - - for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { - contentWidth -= ascCharWidth; - } - - var ellipsisWidth = getWidth(ellipsis, font); - - if (ellipsisWidth > contentWidth) { - ellipsis = ''; - ellipsisWidth = 0; - } - - contentWidth = containerWidth - ellipsisWidth; - preparedOpts.ellipsis = ellipsis; - preparedOpts.ellipsisWidth = ellipsisWidth; - preparedOpts.contentWidth = contentWidth; - preparedOpts.containerWidth = containerWidth; - return preparedOpts; - } - - function truncateSingleLine(textLine, options) { - var containerWidth = options.containerWidth; - var font = options.font; - var contentWidth = options.contentWidth; - - if (!containerWidth) { - return ''; - } - - var lineWidth = getWidth(textLine, font); - - if (lineWidth <= containerWidth) { - return textLine; - } - - for (var j = 0;; j++) { - if (lineWidth <= contentWidth || j >= options.maxIterations) { - textLine += options.ellipsis; - break; - } - - var subLength = j === 0 ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) : lineWidth > 0 ? Math.floor(textLine.length * contentWidth / lineWidth) : 0; - textLine = textLine.substr(0, subLength); - lineWidth = getWidth(textLine, font); - } - - if (textLine === '') { - textLine = options.placeholder; - } - - return textLine; - } - - function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { - var width = 0; - var i = 0; - - for (var len = text.length; i < len && width < contentWidth; i++) { - var charCode = text.charCodeAt(i); - width += 0 <= charCode && charCode <= 127 ? ascCharWidth : cnCharWidth; - } - - return i; - } - - function parsePlainText(text, style) { - text != null && (text += ''); - var overflow = style.overflow; - var padding = style.padding; - var font = style.font; - var truncate = overflow === 'truncate'; - var calculatedLineHeight = getLineHeight(font); - var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight); - var bgColorDrawn = !!style.backgroundColor; - var truncateLineOverflow = style.lineOverflow === 'truncate'; - var width = style.width; - var lines; - - if (width != null && (overflow === 'break' || overflow === 'breakAll')) { - lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : []; - } else { - lines = text ? text.split('\n') : []; - } - - var contentHeight = lines.length * lineHeight; - var height = retrieve2(style.height, contentHeight); - - if (contentHeight > height && truncateLineOverflow) { - var lineCount = Math.floor(height / lineHeight); - lines = lines.slice(0, lineCount); - } - - if (text && truncate && width != null) { - var options = prepareTruncateOptions(width, font, style.ellipsis, { - minChar: style.truncateMinChar, - placeholder: style.placeholder - }); - - for (var i = 0; i < lines.length; i++) { - lines[i] = truncateSingleLine(lines[i], options); - } - } - - var outerHeight = height; - var contentWidth = 0; - - for (var i = 0; i < lines.length; i++) { - contentWidth = Math.max(getWidth(lines[i], font), contentWidth); - } - - if (width == null) { - width = contentWidth; - } - - var outerWidth = contentWidth; - - if (padding) { - outerHeight += padding[0] + padding[2]; - outerWidth += padding[1] + padding[3]; - width += padding[1] + padding[3]; - } - - if (bgColorDrawn) { - outerWidth = width; - } - - return { - lines: lines, - height: height, - outerWidth: outerWidth, - outerHeight: outerHeight, - lineHeight: lineHeight, - calculatedLineHeight: calculatedLineHeight, - contentWidth: contentWidth, - contentHeight: contentHeight, - width: width - }; - } - - var RichTextToken = function () { - function RichTextToken() {} - - return RichTextToken; - }(); - - var RichTextLine = function () { - function RichTextLine(tokens) { - this.tokens = []; - - if (tokens) { - this.tokens = tokens; - } - } - - return RichTextLine; - }(); - - var RichTextContentBlock = function () { - function RichTextContentBlock() { - this.width = 0; - this.height = 0; - this.contentWidth = 0; - this.contentHeight = 0; - this.outerWidth = 0; - this.outerHeight = 0; - this.lines = []; - } - - return RichTextContentBlock; - }(); - - function parseRichText(text, style) { - var contentBlock = new RichTextContentBlock(); - text != null && (text += ''); - - if (!text) { - return contentBlock; - } - - var topWidth = style.width; - var topHeight = style.height; - var overflow = style.overflow; - var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null ? { - width: topWidth, - accumWidth: 0, - breakAll: overflow === 'breakAll' - } : null; - var lastIndex = STYLE_REG.lastIndex = 0; - var result; - - while ((result = STYLE_REG.exec(text)) != null) { - var matchedIndex = result.index; - - if (matchedIndex > lastIndex) { - pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo); - } - - pushTokens(contentBlock, result[2], style, wrapInfo, result[1]); - lastIndex = STYLE_REG.lastIndex; - } - - if (lastIndex < text.length) { - pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo); - } - - var pendingList = []; - var calculatedHeight = 0; - var calculatedWidth = 0; - var stlPadding = style.padding; - var truncate = overflow === 'truncate'; - var truncateLine = style.lineOverflow === 'truncate'; - - function finishLine(line, lineWidth, lineHeight) { - line.width = lineWidth; - line.lineHeight = lineHeight; - calculatedHeight += lineHeight; - calculatedWidth = Math.max(calculatedWidth, lineWidth); - } - - outer: for (var i = 0; i < contentBlock.lines.length; i++) { - var line = contentBlock.lines[i]; - var lineHeight = 0; - var lineWidth = 0; - - for (var j = 0; j < line.tokens.length; j++) { - var token = line.tokens[j]; - var tokenStyle = token.styleName && style.rich[token.styleName] || {}; - var textPadding = token.textPadding = tokenStyle.padding; - var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0; - var font = token.font = tokenStyle.font || style.font; - token.contentHeight = getLineHeight(font); - var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight); - token.innerHeight = tokenHeight; - textPadding && (tokenHeight += textPadding[0] + textPadding[2]); - token.height = tokenHeight; - token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight); - token.align = tokenStyle && tokenStyle.align || style.align; - token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle'; - - if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) { - if (j > 0) { - line.tokens = line.tokens.slice(0, j); - finishLine(line, lineWidth, lineHeight); - contentBlock.lines = contentBlock.lines.slice(0, i + 1); - } else { - contentBlock.lines = contentBlock.lines.slice(0, i); - } - - break outer; - } - - var styleTokenWidth = tokenStyle.width; - var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto'; - - if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') { - token.percentWidth = styleTokenWidth; - pendingList.push(token); - token.contentWidth = getWidth(token.text, font); - } else { - if (tokenWidthNotSpecified) { - var textBackgroundColor = tokenStyle.backgroundColor; - var bgImg = textBackgroundColor && textBackgroundColor.image; - - if (bgImg) { - bgImg = findExistImage(bgImg); - - if (isImageReady(bgImg)) { - token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height); - } - } - } - - var remainTruncWidth = truncate && topWidth != null ? topWidth - lineWidth : null; - - if (remainTruncWidth != null && remainTruncWidth < token.width) { - if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) { - token.text = ''; - token.width = token.contentWidth = 0; - } else { - token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, { - minChar: style.truncateMinChar - }); - token.width = token.contentWidth = getWidth(token.text, font); - } - } else { - token.contentWidth = getWidth(token.text, font); - } - } - - token.width += paddingH; - lineWidth += token.width; - tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); - } - - finishLine(line, lineWidth, lineHeight); - } - - contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth); - contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight); - contentBlock.contentHeight = calculatedHeight; - contentBlock.contentWidth = calculatedWidth; - - if (stlPadding) { - contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; - contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; - } - - for (var i = 0; i < pendingList.length; i++) { - var token = pendingList[i]; - var percentWidth = token.percentWidth; - token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width; - } - - return contentBlock; - } - - function pushTokens(block, str, style, wrapInfo, styleName) { - var isEmptyStr = str === ''; - var tokenStyle = styleName && style.rich[styleName] || {}; - var lines = block.lines; - var font = tokenStyle.font || style.font; - var newLine = false; - var strLines; - var linesWidths; - - if (wrapInfo) { - var tokenPadding = tokenStyle.padding; - var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0; - - if (tokenStyle.width != null && tokenStyle.width !== 'auto') { - var outerWidth_1 = parsePercent$1(tokenStyle.width, wrapInfo.width) + tokenPaddingH; - - if (lines.length > 0) { - if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) { - strLines = str.split('\n'); - newLine = true; - } - } - - wrapInfo.accumWidth = outerWidth_1; - } else { - var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth); - wrapInfo.accumWidth = res.accumWidth + tokenPaddingH; - linesWidths = res.linesWidths; - strLines = res.lines; - } - } else { - strLines = str.split('\n'); - } - - for (var i = 0; i < strLines.length; i++) { - var text = strLines[i]; - var token = new RichTextToken(); - token.styleName = styleName; - token.text = text; - token.isLineHolder = !text && !isEmptyStr; - - if (typeof tokenStyle.width === 'number') { - token.width = tokenStyle.width; - } else { - token.width = linesWidths ? linesWidths[i] : getWidth(text, font); - } - - if (!i && !newLine) { - var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens; - var tokensLen = tokens.length; - tokensLen === 1 && tokens[0].isLineHolder ? tokens[0] = token : (text || !tokensLen || isEmptyStr) && tokens.push(token); - } else { - lines.push(new RichTextLine([token])); - } - } - } - - function isAlphabeticLetter(ch) { - var code = ch.charCodeAt(0); - return code >= 0x20 && code <= 0x24F || code >= 0x370 && code <= 0x10FF || code >= 0x1200 && code <= 0x13FF || code >= 0x1E00 && code <= 0x206F; - } - - var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) { - obj[ch] = true; - return obj; - }, {}); - - function isWordBreakChar(ch) { - if (isAlphabeticLetter(ch)) { - if (breakCharMap[ch]) { - return true; - } - - return false; - } - - return true; - } - - function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) { - var lines = []; - var linesWidths = []; - var line = ''; - var currentWord = ''; - var currentWordWidth = 0; - var accumWidth = 0; - - for (var i = 0; i < text.length; i++) { - var ch = text.charAt(i); - - if (ch === '\n') { - if (currentWord) { - line += currentWord; - accumWidth += currentWordWidth; - } - - lines.push(line); - linesWidths.push(accumWidth); - line = ''; - currentWord = ''; - currentWordWidth = 0; - accumWidth = 0; - continue; - } - - var chWidth = getWidth(ch, font); - var inWord = isBreakAll ? false : !isWordBreakChar(ch); - - if (!lines.length ? lastAccumWidth + accumWidth + chWidth > lineWidth : accumWidth + chWidth > lineWidth) { - if (!accumWidth) { - if (inWord) { - lines.push(currentWord); - linesWidths.push(currentWordWidth); - currentWord = ch; - currentWordWidth = chWidth; - } else { - lines.push(ch); - linesWidths.push(chWidth); - } - } else if (line || currentWord) { - if (inWord) { - if (!line) { - line = currentWord; - currentWord = ''; - currentWordWidth = 0; - accumWidth = currentWordWidth; - } - - lines.push(line); - linesWidths.push(accumWidth - currentWordWidth); - currentWord += ch; - currentWordWidth += chWidth; - line = ''; - accumWidth = currentWordWidth; - } else { - if (currentWord) { - line += currentWord; - currentWord = ''; - currentWordWidth = 0; - } - - lines.push(line); - linesWidths.push(accumWidth); - line = ch; - accumWidth = chWidth; - } - } - - continue; - } - - accumWidth += chWidth; - - if (inWord) { - currentWord += ch; - currentWordWidth += chWidth; - } else { - if (currentWord) { - line += currentWord; - currentWord = ''; - currentWordWidth = 0; - } - - line += ch; - } - } - - if (!lines.length && !line) { - line = text; - currentWord = ''; - currentWordWidth = 0; - } - - if (currentWord) { - line += currentWord; - } - - if (line) { - lines.push(line); - linesWidths.push(accumWidth); - } - - if (lines.length === 1) { - accumWidth += lastAccumWidth; - } - - return { - accumWidth: accumWidth, - lines: lines, - linesWidths: linesWidths - }; - } - - var STYLE_MAGIC_KEY = '__zr_style_' + Math.round(Math.random() * 10); - var DEFAULT_COMMON_STYLE = { - shadowBlur: 0, - shadowOffsetX: 0, - shadowOffsetY: 0, - shadowColor: '#000', - opacity: 1, - blend: 'source-over' - }; - var DEFAULT_COMMON_ANIMATION_PROPS = { - style: { - shadowBlur: true, - shadowOffsetX: true, - shadowOffsetY: true, - shadowColor: true, - opacity: true - } - }; - DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true; - var PRIMARY_STATES_KEYS = ['z', 'z2', 'invisible']; - var PRIMARY_STATES_KEYS_IN_HOVER_LAYER = ['invisible']; - - var Displayable = function (_super) { - __extends(Displayable, _super); - - function Displayable(props) { - return _super.call(this, props) || this; - } - - Displayable.prototype._init = function (props) { - var keysArr = keys(props); - - for (var i = 0; i < keysArr.length; i++) { - var key = keysArr[i]; - - if (key === 'style') { - this.useStyle(props[key]); - } else { - _super.prototype.attrKV.call(this, key, props[key]); - } - } - - if (!this.style) { - this.useStyle({}); - } - }; - - Displayable.prototype.beforeBrush = function () {}; - - Displayable.prototype.afterBrush = function () {}; - - Displayable.prototype.innerBeforeBrush = function () {}; - - Displayable.prototype.innerAfterBrush = function () {}; - - Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) { - var m = this.transform; - - if (this.ignore || this.invisible || this.style.opacity === 0 || this.culling && isDisplayableCulled(this, viewWidth, viewHeight) || m && !m[0] && !m[3]) { - return false; - } - - if (considerClipPath && this.__clipPaths) { - for (var i = 0; i < this.__clipPaths.length; ++i) { - if (this.__clipPaths[i].isZeroArea()) { - return false; - } - } - } - - if (considerAncestors && this.parent) { - var parent_1 = this.parent; - - while (parent_1) { - if (parent_1.ignore) { - return false; - } - - parent_1 = parent_1.parent; - } - } - - return true; - }; - - Displayable.prototype.contain = function (x, y) { - return this.rectContain(x, y); - }; - - Displayable.prototype.traverse = function (cb, context) { - cb.call(context, this); - }; - - Displayable.prototype.rectContain = function (x, y) { - var coord = this.transformCoordToLocal(x, y); - var rect = this.getBoundingRect(); - return rect.contain(coord[0], coord[1]); - }; - - Displayable.prototype.getPaintRect = function () { - var rect = this._paintRect; - - if (!this._paintRect || this.__dirty) { - var transform = this.transform; - var elRect = this.getBoundingRect(); - var style = this.style; - var shadowSize = style.shadowBlur || 0; - var shadowOffsetX = style.shadowOffsetX || 0; - var shadowOffsetY = style.shadowOffsetY || 0; - rect = this._paintRect || (this._paintRect = new BoundingRect(0, 0, 0, 0)); - - if (transform) { - BoundingRect.applyTransform(rect, elRect, transform); - } else { - rect.copy(elRect); - } - - if (shadowSize || shadowOffsetX || shadowOffsetY) { - rect.width += shadowSize * 2 + Math.abs(shadowOffsetX); - rect.height += shadowSize * 2 + Math.abs(shadowOffsetY); - rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize); - rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize); - } - - var tolerance = this.dirtyRectTolerance; - - if (!rect.isZero()) { - rect.x = Math.floor(rect.x - tolerance); - rect.y = Math.floor(rect.y - tolerance); - rect.width = Math.ceil(rect.width + 1 + tolerance * 2); - rect.height = Math.ceil(rect.height + 1 + tolerance * 2); - } - } - - return rect; - }; - - Displayable.prototype.setPrevPaintRect = function (paintRect) { - if (paintRect) { - this._prevPaintRect = this._prevPaintRect || new BoundingRect(0, 0, 0, 0); - - this._prevPaintRect.copy(paintRect); - } else { - this._prevPaintRect = null; - } - }; - - Displayable.prototype.getPrevPaintRect = function () { - return this._prevPaintRect; - }; - - Displayable.prototype.animateStyle = function (loop) { - return this.animate('style', loop); - }; - - Displayable.prototype.updateDuringAnimation = function (targetKey) { - if (targetKey === 'style') { - this.dirtyStyle(); - } else { - this.markRedraw(); - } - }; - - Displayable.prototype.attrKV = function (key, value) { - if (key !== 'style') { - _super.prototype.attrKV.call(this, key, value); - } else { - if (!this.style) { - this.useStyle(value); - } else { - this.setStyle(value); - } - } - }; - - Displayable.prototype.setStyle = function (keyOrObj, value) { - if (typeof keyOrObj === 'string') { - this.style[keyOrObj] = value; - } else { - extend(this.style, keyOrObj); - } - - this.dirtyStyle(); - return this; - }; - - Displayable.prototype.dirtyStyle = function (notRedraw) { - if (!notRedraw) { - this.markRedraw(); - } - - this.__dirty |= STYLE_CHANGED_BIT; - - if (this._rect) { - this._rect = null; - } - }; - - Displayable.prototype.dirty = function () { - this.dirtyStyle(); - }; - - Displayable.prototype.styleChanged = function () { - return !!(this.__dirty & STYLE_CHANGED_BIT); - }; - - Displayable.prototype.styleUpdated = function () { - this.__dirty &= ~STYLE_CHANGED_BIT; - }; - - Displayable.prototype.createStyle = function (obj) { - return createObject(DEFAULT_COMMON_STYLE, obj); - }; - - Displayable.prototype.useStyle = function (obj) { - if (!obj[STYLE_MAGIC_KEY]) { - obj = this.createStyle(obj); - } - - if (this.__inHover) { - this.__hoverStyle = obj; - } else { - this.style = obj; - } - - this.dirtyStyle(); - }; - - Displayable.prototype.isStyleObject = function (obj) { - return obj[STYLE_MAGIC_KEY]; - }; - - Displayable.prototype._innerSaveToNormal = function (toState) { - _super.prototype._innerSaveToNormal.call(this, toState); - - var normalState = this._normalState; - - if (toState.style && !normalState.style) { - normalState.style = this._mergeStyle(this.createStyle(), this.style); - } - - this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS); - }; - - Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { - _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); - - var needsRestoreToNormal = !(state && keepCurrentStates); - var targetStyle; - - if (state && state.style) { - if (transition) { - if (keepCurrentStates) { - targetStyle = state.style; - } else { - targetStyle = this._mergeStyle(this.createStyle(), normalState.style); - - this._mergeStyle(targetStyle, state.style); - } - } else { - targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style); - - this._mergeStyle(targetStyle, state.style); - } - } else if (needsRestoreToNormal) { - targetStyle = normalState.style; - } - - if (targetStyle) { - if (transition) { - var sourceStyle = this.style; - this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle); - - if (needsRestoreToNormal) { - var changedKeys = keys(sourceStyle); - - for (var i = 0; i < changedKeys.length; i++) { - var key = changedKeys[i]; - - if (key in targetStyle) { - targetStyle[key] = targetStyle[key]; - this.style[key] = sourceStyle[key]; - } - } - } - - var targetKeys = keys(targetStyle); - - for (var i = 0; i < targetKeys.length; i++) { - var key = targetKeys[i]; - this.style[key] = this.style[key]; - } - - this._transitionState(stateName, { - style: targetStyle - }, animationCfg, this.getAnimationStyleProps()); - } else { - this.useStyle(targetStyle); - } - } - - var statesKeys = this.__inHover ? PRIMARY_STATES_KEYS_IN_HOVER_LAYER : PRIMARY_STATES_KEYS; - - for (var i = 0; i < statesKeys.length; i++) { - var key = statesKeys[i]; - - if (state && state[key] != null) { - this[key] = state[key]; - } else if (needsRestoreToNormal) { - if (normalState[key] != null) { - this[key] = normalState[key]; - } - } - } - }; - - Displayable.prototype._mergeStates = function (states) { - var mergedState = _super.prototype._mergeStates.call(this, states); - - var mergedStyle; - - for (var i = 0; i < states.length; i++) { - var state = states[i]; - - if (state.style) { - mergedStyle = mergedStyle || {}; - - this._mergeStyle(mergedStyle, state.style); - } - } - - if (mergedStyle) { - mergedState.style = mergedStyle; - } - - return mergedState; - }; - - Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) { - extend(targetStyle, sourceStyle); - return targetStyle; - }; - - Displayable.prototype.getAnimationStyleProps = function () { - return DEFAULT_COMMON_ANIMATION_PROPS; - }; - - Displayable.initDefaultProps = function () { - var dispProto = Displayable.prototype; - dispProto.type = 'displayable'; - dispProto.invisible = false; - dispProto.z = 0; - dispProto.z2 = 0; - dispProto.zlevel = 0; - dispProto.culling = false; - dispProto.cursor = 'pointer'; - dispProto.rectHover = false; - dispProto.incremental = false; - dispProto._rect = null; - dispProto.dirtyRectTolerance = 0; - dispProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT; - }(); - - return Displayable; - }(Element); - - var tmpRect = new BoundingRect(0, 0, 0, 0); - var viewRect = new BoundingRect(0, 0, 0, 0); - - function isDisplayableCulled(el, width, height) { - tmpRect.copy(el.getBoundingRect()); - - if (el.transform) { - tmpRect.applyTransform(el.transform); - } - - viewRect.width = width; - viewRect.height = height; - return !tmpRect.intersect(viewRect); - } - - var mathMin$5 = Math.min; - var mathMax$5 = Math.max; - var mathSin$4 = Math.sin; - var mathCos$4 = Math.cos; - var PI2$8 = Math.PI * 2; - var start = create$1(); - var end = create$1(); - var extremity = create$1(); - - function fromLine(x0, y0, x1, y1, min, max) { - min[0] = mathMin$5(x0, x1); - min[1] = mathMin$5(y0, y1); - max[0] = mathMax$5(x0, x1); - max[1] = mathMax$5(y0, y1); - } - - var xDim = []; - var yDim = []; - - function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) { - var cubicExtrema$1 = cubicExtrema; - var cubicAt$1 = cubicAt; - var n = cubicExtrema$1(x0, x1, x2, x3, xDim); - min[0] = Infinity; - min[1] = Infinity; - max[0] = -Infinity; - max[1] = -Infinity; - - for (var i = 0; i < n; i++) { - var x = cubicAt$1(x0, x1, x2, x3, xDim[i]); - min[0] = mathMin$5(x, min[0]); - max[0] = mathMax$5(x, max[0]); - } - - n = cubicExtrema$1(y0, y1, y2, y3, yDim); - - for (var i = 0; i < n; i++) { - var y = cubicAt$1(y0, y1, y2, y3, yDim[i]); - min[1] = mathMin$5(y, min[1]); - max[1] = mathMax$5(y, max[1]); - } - - min[0] = mathMin$5(x0, min[0]); - max[0] = mathMax$5(x0, max[0]); - min[0] = mathMin$5(x3, min[0]); - max[0] = mathMax$5(x3, max[0]); - min[1] = mathMin$5(y0, min[1]); - max[1] = mathMax$5(y0, max[1]); - min[1] = mathMin$5(y3, min[1]); - max[1] = mathMax$5(y3, max[1]); - } - - function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) { - var quadraticExtremum$1 = quadraticExtremum; - var quadraticAt$1 = quadraticAt; - var tx = mathMax$5(mathMin$5(quadraticExtremum$1(x0, x1, x2), 1), 0); - var ty = mathMax$5(mathMin$5(quadraticExtremum$1(y0, y1, y2), 1), 0); - var x = quadraticAt$1(x0, x1, x2, tx); - var y = quadraticAt$1(y0, y1, y2, ty); - min[0] = mathMin$5(x0, x2, x); - min[1] = mathMin$5(y0, y2, y); - max[0] = mathMax$5(x0, x2, x); - max[1] = mathMax$5(y0, y2, y); - } - - function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max) { - var vec2Min = min$1; - var vec2Max = max$1; - var diff = Math.abs(startAngle - endAngle); - - if (diff % PI2$8 < 1e-4 && diff > 1e-4) { - min[0] = x - rx; - min[1] = y - ry; - max[0] = x + rx; - max[1] = y + ry; - return; - } - - start[0] = mathCos$4(startAngle) * rx + x; - start[1] = mathSin$4(startAngle) * ry + y; - end[0] = mathCos$4(endAngle) * rx + x; - end[1] = mathSin$4(endAngle) * ry + y; - vec2Min(min, start, end); - vec2Max(max, start, end); - startAngle = startAngle % PI2$8; - - if (startAngle < 0) { - startAngle = startAngle + PI2$8; - } - - endAngle = endAngle % PI2$8; - - if (endAngle < 0) { - endAngle = endAngle + PI2$8; - } - - if (startAngle > endAngle && !anticlockwise) { - endAngle += PI2$8; - } else if (startAngle < endAngle && anticlockwise) { - startAngle += PI2$8; - } - - if (anticlockwise) { - var tmp = endAngle; - endAngle = startAngle; - startAngle = tmp; - } - - for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { - if (angle > startAngle) { - extremity[0] = mathCos$4(angle) * rx + x; - extremity[1] = mathSin$4(angle) * ry + y; - vec2Min(min, extremity, min); - vec2Max(max, extremity, max); - } - } - } - - var CMD$3 = { - M: 1, - L: 2, - C: 3, - Q: 4, - A: 5, - Z: 6, - R: 7 - }; - var tmpOutX = []; - var tmpOutY = []; - var min = []; - var max = []; - var min2 = []; - var max2 = []; - var mathMin$4 = Math.min; - var mathMax$4 = Math.max; - var mathCos$3 = Math.cos; - var mathSin$3 = Math.sin; - var mathAbs$1 = Math.abs; - var PI$5 = Math.PI; - var PI2$7 = PI$5 * 2; - var hasTypedArray = typeof Float32Array !== 'undefined'; - var tmpAngles = []; - - function modPI2(radian) { - var n = Math.round(radian / PI$5 * 1e8) / 1e8; - return n % 2 * PI$5; - } - - function normalizeArcAngles(angles, anticlockwise) { - var newStartAngle = modPI2(angles[0]); - - if (newStartAngle < 0) { - newStartAngle += PI2$7; - } - - var delta = newStartAngle - angles[0]; - var newEndAngle = angles[1]; - newEndAngle += delta; - - if (!anticlockwise && newEndAngle - newStartAngle >= PI2$7) { - newEndAngle = newStartAngle + PI2$7; - } else if (anticlockwise && newStartAngle - newEndAngle >= PI2$7) { - newEndAngle = newStartAngle - PI2$7; - } else if (!anticlockwise && newStartAngle > newEndAngle) { - newEndAngle = newStartAngle + (PI2$7 - modPI2(newStartAngle - newEndAngle)); - } else if (anticlockwise && newStartAngle < newEndAngle) { - newEndAngle = newStartAngle - (PI2$7 - modPI2(newEndAngle - newStartAngle)); - } - - angles[0] = newStartAngle; - angles[1] = newEndAngle; - } - - var PathProxy = function () { - function PathProxy(notSaveData) { - this.dpr = 1; - this._xi = 0; - this._yi = 0; - this._x0 = 0; - this._y0 = 0; - this._len = 0; - - if (notSaveData) { - this._saveData = false; - } - - if (this._saveData) { - this.data = []; - } - } - - PathProxy.prototype.increaseVersion = function () { - this._version++; - }; - - PathProxy.prototype.getVersion = function () { - return this._version; - }; - - PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) { - segmentIgnoreThreshold = segmentIgnoreThreshold || 0; - - if (segmentIgnoreThreshold > 0) { - this._ux = mathAbs$1(segmentIgnoreThreshold / devicePixelRatio / sx) || 0; - this._uy = mathAbs$1(segmentIgnoreThreshold / devicePixelRatio / sy) || 0; - } - }; - - PathProxy.prototype.setDPR = function (dpr) { - this.dpr = dpr; - }; - - PathProxy.prototype.setContext = function (ctx) { - this._ctx = ctx; - }; - - PathProxy.prototype.getContext = function () { - return this._ctx; - }; - - PathProxy.prototype.beginPath = function () { - this._ctx && this._ctx.beginPath(); - this.reset(); - return this; - }; - - PathProxy.prototype.reset = function () { - if (this._saveData) { - this._len = 0; - } - - if (this._pathSegLen) { - this._pathSegLen = null; - this._pathLen = 0; - } - - this._version++; - }; - - PathProxy.prototype.moveTo = function (x, y) { - this._drawPendingPt(); - - this.addData(CMD$3.M, x, y); - this._ctx && this._ctx.moveTo(x, y); - this._x0 = x; - this._y0 = y; - this._xi = x; - this._yi = y; - return this; - }; - - PathProxy.prototype.lineTo = function (x, y) { - var dx = mathAbs$1(x - this._xi); - var dy = mathAbs$1(y - this._yi); - var exceedUnit = dx > this._ux || dy > this._uy; - this.addData(CMD$3.L, x, y); - - if (this._ctx && exceedUnit) { - this._ctx.lineTo(x, y); - } - - if (exceedUnit) { - this._xi = x; - this._yi = y; - this._pendingPtDist = 0; - } else { - var d2 = dx * dx + dy * dy; - - if (d2 > this._pendingPtDist) { - this._pendingPtX = x; - this._pendingPtY = y; - this._pendingPtDist = d2; - } - } - - return this; - }; - - PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) { - this._drawPendingPt(); - - this.addData(CMD$3.C, x1, y1, x2, y2, x3, y3); - - if (this._ctx) { - this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); - } - - this._xi = x3; - this._yi = y3; - return this; - }; - - PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) { - this._drawPendingPt(); - - this.addData(CMD$3.Q, x1, y1, x2, y2); - - if (this._ctx) { - this._ctx.quadraticCurveTo(x1, y1, x2, y2); - } - - this._xi = x2; - this._yi = y2; - return this; - }; - - PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { - this._drawPendingPt(); - - tmpAngles[0] = startAngle; - tmpAngles[1] = endAngle; - normalizeArcAngles(tmpAngles, anticlockwise); - startAngle = tmpAngles[0]; - endAngle = tmpAngles[1]; - var delta = endAngle - startAngle; - this.addData(CMD$3.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1); - this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); - this._xi = mathCos$3(endAngle) * r + cx; - this._yi = mathSin$3(endAngle) * r + cy; - return this; - }; - - PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) { - this._drawPendingPt(); - - if (this._ctx) { - this._ctx.arcTo(x1, y1, x2, y2, radius); - } - - return this; - }; - - PathProxy.prototype.rect = function (x, y, w, h) { - this._drawPendingPt(); - - this._ctx && this._ctx.rect(x, y, w, h); - this.addData(CMD$3.R, x, y, w, h); - return this; - }; - - PathProxy.prototype.closePath = function () { - this._drawPendingPt(); - - this.addData(CMD$3.Z); - var ctx = this._ctx; - var x0 = this._x0; - var y0 = this._y0; - - if (ctx) { - ctx.closePath(); - } - - this._xi = x0; - this._yi = y0; - return this; - }; - - PathProxy.prototype.fill = function (ctx) { - ctx && ctx.fill(); - this.toStatic(); - }; - - PathProxy.prototype.stroke = function (ctx) { - ctx && ctx.stroke(); - this.toStatic(); - }; - - PathProxy.prototype.len = function () { - return this._len; - }; - - PathProxy.prototype.setData = function (data) { - var len = data.length; - - if (!(this.data && this.data.length === len) && hasTypedArray) { - this.data = new Float32Array(len); - } - - for (var i = 0; i < len; i++) { - this.data[i] = data[i]; - } - - this._len = len; - }; - - PathProxy.prototype.appendPath = function (path) { - if (!(path instanceof Array)) { - path = [path]; - } - - var len = path.length; - var appendSize = 0; - var offset = this._len; - - for (var i = 0; i < len; i++) { - appendSize += path[i].len(); - } - - if (hasTypedArray && this.data instanceof Float32Array) { - this.data = new Float32Array(offset + appendSize); - } - - for (var i = 0; i < len; i++) { - var appendPathData = path[i].data; - - for (var k = 0; k < appendPathData.length; k++) { - this.data[offset++] = appendPathData[k]; - } - } - - this._len = offset; - }; - - PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) { - if (!this._saveData) { - return; - } - - var data = this.data; - - if (this._len + arguments.length > data.length) { - this._expandData(); - - data = this.data; - } - - for (var i = 0; i < arguments.length; i++) { - data[this._len++] = arguments[i]; - } - }; - - PathProxy.prototype._drawPendingPt = function () { - if (this._pendingPtDist > 0) { - this._ctx && this._ctx.lineTo(this._pendingPtX, this._pendingPtY); - this._pendingPtDist = 0; - } - }; - - PathProxy.prototype._expandData = function () { - if (!(this.data instanceof Array)) { - var newData = []; - - for (var i = 0; i < this._len; i++) { - newData[i] = this.data[i]; - } - - this.data = newData; - } - }; - - PathProxy.prototype.toStatic = function () { - if (!this._saveData) { - return; - } - - this._drawPendingPt(); - - var data = this.data; - - if (data instanceof Array) { - data.length = this._len; - - if (hasTypedArray && this._len > 11) { - this.data = new Float32Array(data); - } - } - }; - - PathProxy.prototype.getBoundingRect = function () { - min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE; - max[0] = max[1] = max2[0] = max2[1] = -Number.MAX_VALUE; - var data = this.data; - var xi = 0; - var yi = 0; - var x0 = 0; - var y0 = 0; - var i; - - for (i = 0; i < this._len;) { - var cmd = data[i++]; - var isFirst = i === 1; - - if (isFirst) { - xi = data[i]; - yi = data[i + 1]; - x0 = xi; - y0 = yi; - } - - switch (cmd) { - case CMD$3.M: - xi = x0 = data[i++]; - yi = y0 = data[i++]; - min2[0] = x0; - min2[1] = y0; - max2[0] = x0; - max2[1] = y0; - break; - - case CMD$3.L: - fromLine(xi, yi, data[i], data[i + 1], min2, max2); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$3.C: - fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$3.Q: - fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$3.A: - var cx = data[i++]; - var cy = data[i++]; - var rx = data[i++]; - var ry = data[i++]; - var startAngle = data[i++]; - var endAngle = data[i++] + startAngle; - i += 1; - var anticlockwise = !data[i++]; - - if (isFirst) { - x0 = mathCos$3(startAngle) * rx + cx; - y0 = mathSin$3(startAngle) * ry + cy; - } - - fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2); - xi = mathCos$3(endAngle) * rx + cx; - yi = mathSin$3(endAngle) * ry + cy; - break; - - case CMD$3.R: - x0 = xi = data[i++]; - y0 = yi = data[i++]; - var width = data[i++]; - var height = data[i++]; - fromLine(x0, y0, x0 + width, y0 + height, min2, max2); - break; - - case CMD$3.Z: - xi = x0; - yi = y0; - break; - } - - min$1(min, min, min2); - max$1(max, max, max2); - } - - if (i === 0) { - min[0] = min[1] = max[0] = max[1] = 0; - } - - return new BoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); - }; - - PathProxy.prototype._calculateLength = function () { - var data = this.data; - var len = this._len; - var ux = this._ux; - var uy = this._uy; - var xi = 0; - var yi = 0; - var x0 = 0; - var y0 = 0; - - if (!this._pathSegLen) { - this._pathSegLen = []; - } - - var pathSegLen = this._pathSegLen; - var pathTotalLen = 0; - var segCount = 0; - - for (var i = 0; i < len;) { - var cmd = data[i++]; - var isFirst = i === 1; - - if (isFirst) { - xi = data[i]; - yi = data[i + 1]; - x0 = xi; - y0 = yi; - } - - var l = -1; - - switch (cmd) { - case CMD$3.M: - xi = x0 = data[i++]; - yi = y0 = data[i++]; - break; - - case CMD$3.L: - { - var x2 = data[i++]; - var y2 = data[i++]; - var dx = x2 - xi; - var dy = y2 - yi; - - if (mathAbs$1(dx) > ux || mathAbs$1(dy) > uy || i === len - 1) { - l = Math.sqrt(dx * dx + dy * dy); - xi = x2; - yi = y2; - } - - break; - } - - case CMD$3.C: - { - var x1 = data[i++]; - var y1 = data[i++]; - var x2 = data[i++]; - var y2 = data[i++]; - var x3 = data[i++]; - var y3 = data[i++]; - l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10); - xi = x3; - yi = y3; - break; - } - - case CMD$3.Q: - { - var x1 = data[i++]; - var y1 = data[i++]; - var x2 = data[i++]; - var y2 = data[i++]; - l = quadraticLength(xi, yi, x1, y1, x2, y2, 10); - xi = x2; - yi = y2; - break; - } - - case CMD$3.A: - var cx = data[i++]; - var cy = data[i++]; - var rx = data[i++]; - var ry = data[i++]; - var startAngle = data[i++]; - var delta = data[i++]; - var endAngle = delta + startAngle; - i += 1; - - if (isFirst) { - x0 = mathCos$3(startAngle) * rx + cx; - y0 = mathSin$3(startAngle) * ry + cy; - } - - l = mathMax$4(rx, ry) * mathMin$4(PI2$7, Math.abs(delta)); - xi = mathCos$3(endAngle) * rx + cx; - yi = mathSin$3(endAngle) * ry + cy; - break; - - case CMD$3.R: - { - x0 = xi = data[i++]; - y0 = yi = data[i++]; - var width = data[i++]; - var height = data[i++]; - l = width * 2 + height * 2; - break; - } - - case CMD$3.Z: - { - var dx = x0 - xi; - var dy = y0 - yi; - l = Math.sqrt(dx * dx + dy * dy); - xi = x0; - yi = y0; - break; - } - } - - if (l >= 0) { - pathSegLen[segCount++] = l; - pathTotalLen += l; - } - } - - this._pathLen = pathTotalLen; - return pathTotalLen; - }; - - PathProxy.prototype.rebuildPath = function (ctx, percent) { - var d = this.data; - var ux = this._ux; - var uy = this._uy; - var len = this._len; - var x0; - var y0; - var xi; - var yi; - var x; - var y; - var drawPart = percent < 1; - var pathSegLen; - var pathTotalLen; - var accumLength = 0; - var segCount = 0; - var displayedLength; - var pendingPtDist = 0; - var pendingPtX; - var pendingPtY; - - if (drawPart) { - if (!this._pathSegLen) { - this._calculateLength(); - } - - pathSegLen = this._pathSegLen; - pathTotalLen = this._pathLen; - displayedLength = percent * pathTotalLen; - - if (!displayedLength) { - return; - } - } - - lo: for (var i = 0; i < len;) { - var cmd = d[i++]; - var isFirst = i === 1; - - if (isFirst) { - xi = d[i]; - yi = d[i + 1]; - x0 = xi; - y0 = yi; - } - - if (cmd !== CMD$3.L && pendingPtDist > 0) { - ctx.lineTo(pendingPtX, pendingPtY); - pendingPtDist = 0; - } - - switch (cmd) { - case CMD$3.M: - x0 = xi = d[i++]; - y0 = yi = d[i++]; - ctx.moveTo(xi, yi); - break; - - case CMD$3.L: - { - x = d[i++]; - y = d[i++]; - var dx = mathAbs$1(x - xi); - var dy = mathAbs$1(y - yi); - - if (dx > ux || dy > uy) { - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - var t = (displayedLength - accumLength) / l; - ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t); - break lo; - } - - accumLength += l; - } - - ctx.lineTo(x, y); - xi = x; - yi = y; - pendingPtDist = 0; - } else { - var d2 = dx * dx + dy * dy; - - if (d2 > pendingPtDist) { - pendingPtX = x; - pendingPtY = y; - pendingPtDist = d2; - } - } - - break; - } - - case CMD$3.C: - { - var x1 = d[i++]; - var y1 = d[i++]; - var x2 = d[i++]; - var y2 = d[i++]; - var x3 = d[i++]; - var y3 = d[i++]; - - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - var t = (displayedLength - accumLength) / l; - cubicSubdivide(xi, x1, x2, x3, t, tmpOutX); - cubicSubdivide(yi, y1, y2, y3, t, tmpOutY); - ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]); - break lo; - } - - accumLength += l; - } - - ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); - xi = x3; - yi = y3; - break; - } - - case CMD$3.Q: - { - var x1 = d[i++]; - var y1 = d[i++]; - var x2 = d[i++]; - var y2 = d[i++]; - - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - var t = (displayedLength - accumLength) / l; - quadraticSubdivide(xi, x1, x2, t, tmpOutX); - quadraticSubdivide(yi, y1, y2, t, tmpOutY); - ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]); - break lo; - } - - accumLength += l; - } - - ctx.quadraticCurveTo(x1, y1, x2, y2); - xi = x2; - yi = y2; - break; - } - - case CMD$3.A: - var cx = d[i++]; - var cy = d[i++]; - var rx = d[i++]; - var ry = d[i++]; - var startAngle = d[i++]; - var delta = d[i++]; - var psi = d[i++]; - var anticlockwise = !d[i++]; - var r = rx > ry ? rx : ry; - var isEllipse = mathAbs$1(rx - ry) > 1e-3; - var endAngle = startAngle + delta; - var breakBuild = false; - - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - endAngle = startAngle + delta * (displayedLength - accumLength) / l; - breakBuild = true; - } - - accumLength += l; - } - - if (isEllipse && ctx.ellipse) { - ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise); - } else { - ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); - } - - if (breakBuild) { - break lo; - } - - if (isFirst) { - x0 = mathCos$3(startAngle) * rx + cx; - y0 = mathSin$3(startAngle) * ry + cy; - } - - xi = mathCos$3(endAngle) * rx + cx; - yi = mathSin$3(endAngle) * ry + cy; - break; - - case CMD$3.R: - x0 = xi = d[i]; - y0 = yi = d[i + 1]; - x = d[i++]; - y = d[i++]; - var width = d[i++]; - var height = d[i++]; - - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - var d_1 = displayedLength - accumLength; - ctx.moveTo(x, y); - ctx.lineTo(x + mathMin$4(d_1, width), y); - d_1 -= width; - - if (d_1 > 0) { - ctx.lineTo(x + width, y + mathMin$4(d_1, height)); - } - - d_1 -= height; - - if (d_1 > 0) { - ctx.lineTo(x + mathMax$4(width - d_1, 0), y + height); - } - - d_1 -= width; - - if (d_1 > 0) { - ctx.lineTo(x, y + mathMax$4(height - d_1, 0)); - } - - break lo; - } - - accumLength += l; - } - - ctx.rect(x, y, width, height); - break; - - case CMD$3.Z: - if (drawPart) { - var l = pathSegLen[segCount++]; - - if (accumLength + l > displayedLength) { - var t = (displayedLength - accumLength) / l; - ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t); - break lo; - } - - accumLength += l; - } - - ctx.closePath(); - xi = x0; - yi = y0; - } - } - }; - - PathProxy.prototype.clone = function () { - var newProxy = new PathProxy(); - var data = this.data; - newProxy.data = data.slice ? data.slice() : Array.prototype.slice.call(data); - newProxy._len = this._len; - return newProxy; - }; - - PathProxy.CMD = CMD$3; - - PathProxy.initDefaultProps = function () { - var proto = PathProxy.prototype; - proto._saveData = true; - proto._ux = 0; - proto._uy = 0; - proto._pendingPtDist = 0; - proto._version = 0; - }(); - - return PathProxy; - }(); - - function containStroke$4(x0, y0, x1, y1, lineWidth, x, y) { - if (lineWidth === 0) { - return false; - } - - var _l = lineWidth; - var _a = 0; - var _b = x0; - - if (y > y0 + _l && y > y1 + _l || y < y0 - _l && y < y1 - _l || x > x0 + _l && x > x1 + _l || x < x0 - _l && x < x1 - _l) { - return false; - } - - if (x0 !== x1) { - _a = (y0 - y1) / (x0 - x1); - _b = (x0 * y1 - x1 * y0) / (x0 - x1); - } else { - return Math.abs(x - x0) <= _l / 2; - } - - var tmp = _a * x - y + _b; - - var _s = tmp * tmp / (_a * _a + 1); - - return _s <= _l / 2 * _l / 2; - } - - function containStroke$3(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) { - if (lineWidth === 0) { - return false; - } - - var _l = lineWidth; - - if (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l || y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l || x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l || x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l) { - return false; - } - - var d = cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, null); - return d <= _l / 2; - } - - function containStroke$2(x0, y0, x1, y1, x2, y2, lineWidth, x, y) { - if (lineWidth === 0) { - return false; - } - - var _l = lineWidth; - - if (y > y0 + _l && y > y1 + _l && y > y2 + _l || y < y0 - _l && y < y1 - _l && y < y2 - _l || x > x0 + _l && x > x1 + _l && x > x2 + _l || x < x0 - _l && x < x1 - _l && x < x2 - _l) { - return false; - } - - var d = quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, null); - return d <= _l / 2; - } - - var PI2$6 = Math.PI * 2; - - function normalizeRadian(angle) { - angle %= PI2$6; - - if (angle < 0) { - angle += PI2$6; - } - - return angle; - } - - var PI2$5 = Math.PI * 2; - - function containStroke$1(cx, cy, r, startAngle, endAngle, anticlockwise, lineWidth, x, y) { - if (lineWidth === 0) { - return false; - } - - var _l = lineWidth; - x -= cx; - y -= cy; - var d = Math.sqrt(x * x + y * y); - - if (d - _l > r || d + _l < r) { - return false; - } - - if (Math.abs(startAngle - endAngle) % PI2$5 < 1e-4) { - return true; - } - - if (anticlockwise) { - var tmp = startAngle; - startAngle = normalizeRadian(endAngle); - endAngle = normalizeRadian(tmp); - } else { - startAngle = normalizeRadian(startAngle); - endAngle = normalizeRadian(endAngle); - } - - if (startAngle > endAngle) { - endAngle += PI2$5; - } - - var angle = Math.atan2(y, x); - - if (angle < 0) { - angle += PI2$5; - } - - return angle >= startAngle && angle <= endAngle || angle + PI2$5 >= startAngle && angle + PI2$5 <= endAngle; - } - - function windingLine(x0, y0, x1, y1, x, y) { - if (y > y0 && y > y1 || y < y0 && y < y1) { - return 0; - } - - if (y1 === y0) { - return 0; - } - - var t = (y - y0) / (y1 - y0); - var dir = y1 < y0 ? 1 : -1; - - if (t === 1 || t === 0) { - dir = y1 < y0 ? 0.5 : -0.5; - } - - var x_ = t * (x1 - x0) + x0; - return x_ === x ? Infinity : x_ > x ? dir : 0; - } - - var CMD$2 = PathProxy.CMD; - var PI2$4 = Math.PI * 2; - var EPSILON$1 = 1e-4; - - function isAroundEqual$1(a, b) { - return Math.abs(a - b) < EPSILON$1; - } - - var roots = [-1, -1, -1]; - var extrema = [-1, -1]; - - function swapExtrema() { - var tmp = extrema[0]; - extrema[0] = extrema[1]; - extrema[1] = tmp; - } - - function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) { - if (y > y0 && y > y1 && y > y2 && y > y3 || y < y0 && y < y1 && y < y2 && y < y3) { - return 0; - } - - var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots); - - if (nRoots === 0) { - return 0; - } else { - var w = 0; - var nExtrema = -1; - var y0_ = void 0; - var y1_ = void 0; - - for (var i = 0; i < nRoots; i++) { - var t = roots[i]; - var unit = t === 0 || t === 1 ? 0.5 : 1; - var x_ = cubicAt(x0, x1, x2, x3, t); - - if (x_ < x) { - continue; - } - - if (nExtrema < 0) { - nExtrema = cubicExtrema(y0, y1, y2, y3, extrema); - - if (extrema[1] < extrema[0] && nExtrema > 1) { - swapExtrema(); - } - - y0_ = cubicAt(y0, y1, y2, y3, extrema[0]); - - if (nExtrema > 1) { - y1_ = cubicAt(y0, y1, y2, y3, extrema[1]); - } - } - - if (nExtrema === 2) { - if (t < extrema[0]) { - w += y0_ < y0 ? unit : -unit; - } else if (t < extrema[1]) { - w += y1_ < y0_ ? unit : -unit; - } else { - w += y3 < y1_ ? unit : -unit; - } - } else { - if (t < extrema[0]) { - w += y0_ < y0 ? unit : -unit; - } else { - w += y3 < y0_ ? unit : -unit; - } - } - } - - return w; - } - } - - function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) { - if (y > y0 && y > y1 && y > y2 || y < y0 && y < y1 && y < y2) { - return 0; - } - - var nRoots = quadraticRootAt(y0, y1, y2, y, roots); - - if (nRoots === 0) { - return 0; - } else { - var t = quadraticExtremum(y0, y1, y2); - - if (t >= 0 && t <= 1) { - var w = 0; - var y_ = quadraticAt(y0, y1, y2, t); - - for (var i = 0; i < nRoots; i++) { - var unit = roots[i] === 0 || roots[i] === 1 ? 0.5 : 1; - var x_ = quadraticAt(x0, x1, x2, roots[i]); - - if (x_ < x) { - continue; - } - - if (roots[i] < t) { - w += y_ < y0 ? unit : -unit; - } else { - w += y2 < y_ ? unit : -unit; - } - } - - return w; - } else { - var unit = roots[0] === 0 || roots[0] === 1 ? 0.5 : 1; - var x_ = quadraticAt(x0, x1, x2, roots[0]); - - if (x_ < x) { - return 0; - } - - return y2 < y0 ? unit : -unit; - } - } - } - - function windingArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y) { - y -= cy; - - if (y > r || y < -r) { - return 0; - } - - var tmp = Math.sqrt(r * r - y * y); - roots[0] = -tmp; - roots[1] = tmp; - var dTheta = Math.abs(startAngle - endAngle); - - if (dTheta < 1e-4) { - return 0; - } - - if (dTheta >= PI2$4 - 1e-4) { - startAngle = 0; - endAngle = PI2$4; - var dir = anticlockwise ? 1 : -1; - - if (x >= roots[0] + cx && x <= roots[1] + cx) { - return dir; - } else { - return 0; - } - } - - if (startAngle > endAngle) { - var tmp_1 = startAngle; - startAngle = endAngle; - endAngle = tmp_1; - } - - if (startAngle < 0) { - startAngle += PI2$4; - endAngle += PI2$4; - } - - var w = 0; - - for (var i = 0; i < 2; i++) { - var x_ = roots[i]; - - if (x_ + cx > x) { - var angle = Math.atan2(y, x_); - var dir = anticlockwise ? 1 : -1; - - if (angle < 0) { - angle = PI2$4 + angle; - } - - if (angle >= startAngle && angle <= endAngle || angle + PI2$4 >= startAngle && angle + PI2$4 <= endAngle) { - if (angle > Math.PI / 2 && angle < Math.PI * 1.5) { - dir = -dir; - } - - w += dir; - } - } - } - - return w; - } - - function containPath(path, lineWidth, isStroke, x, y) { - var data = path.data; - var len = path.len(); - var w = 0; - var xi = 0; - var yi = 0; - var x0 = 0; - var y0 = 0; - var x1; - var y1; - - for (var i = 0; i < len;) { - var cmd = data[i++]; - var isFirst = i === 1; - - if (cmd === CMD$2.M && i > 1) { - if (!isStroke) { - w += windingLine(xi, yi, x0, y0, x, y); - } - } - - if (isFirst) { - xi = data[i]; - yi = data[i + 1]; - x0 = xi; - y0 = yi; - } - - switch (cmd) { - case CMD$2.M: - x0 = data[i++]; - y0 = data[i++]; - xi = x0; - yi = y0; - break; - - case CMD$2.L: - if (isStroke) { - if (containStroke$4(xi, yi, data[i], data[i + 1], lineWidth, x, y)) { - return true; - } - } else { - w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0; - } - - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$2.C: - if (isStroke) { - if (containStroke$3(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { - return true; - } - } else { - w += windingCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y) || 0; - } - - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$2.Q: - if (isStroke) { - if (containStroke$2(xi, yi, data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { - return true; - } - } else { - w += windingQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y) || 0; - } - - xi = data[i++]; - yi = data[i++]; - break; - - case CMD$2.A: - var cx = data[i++]; - var cy = data[i++]; - var rx = data[i++]; - var ry = data[i++]; - var theta = data[i++]; - var dTheta = data[i++]; - i += 1; - var anticlockwise = !!(1 - data[i++]); - x1 = Math.cos(theta) * rx + cx; - y1 = Math.sin(theta) * ry + cy; - - if (!isFirst) { - w += windingLine(xi, yi, x1, y1, x, y); - } else { - x0 = x1; - y0 = y1; - } - - var _x = (x - cx) * ry / rx + cx; - - if (isStroke) { - if (containStroke$1(cx, cy, ry, theta, theta + dTheta, anticlockwise, lineWidth, _x, y)) { - return true; - } - } else { - w += windingArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y); - } - - xi = Math.cos(theta + dTheta) * rx + cx; - yi = Math.sin(theta + dTheta) * ry + cy; - break; - - case CMD$2.R: - x0 = xi = data[i++]; - y0 = yi = data[i++]; - var width = data[i++]; - var height = data[i++]; - x1 = x0 + width; - y1 = y0 + height; - - if (isStroke) { - if (containStroke$4(x0, y0, x1, y0, lineWidth, x, y) || containStroke$4(x1, y0, x1, y1, lineWidth, x, y) || containStroke$4(x1, y1, x0, y1, lineWidth, x, y) || containStroke$4(x0, y1, x0, y0, lineWidth, x, y)) { - return true; - } - } else { - w += windingLine(x1, y0, x1, y1, x, y); - w += windingLine(x0, y1, x0, y0, x, y); - } - - break; - - case CMD$2.Z: - if (isStroke) { - if (containStroke$4(xi, yi, x0, y0, lineWidth, x, y)) { - return true; - } - } else { - w += windingLine(xi, yi, x0, y0, x, y); - } - - xi = x0; - yi = y0; - break; - } - } - - if (!isStroke && !isAroundEqual$1(yi, y0)) { - w += windingLine(xi, yi, x0, y0, x, y) || 0; - } - - return w !== 0; - } - - function contain$2(pathProxy, x, y) { - return containPath(pathProxy, 0, false, x, y); - } - - function containStroke(pathProxy, lineWidth, x, y) { - return containPath(pathProxy, lineWidth, true, x, y); - } - - var DEFAULT_PATH_STYLE = defaults({ - fill: '#000', - stroke: null, - strokePercent: 1, - fillOpacity: 1, - strokeOpacity: 1, - lineDashOffset: 0, - lineWidth: 1, - lineCap: 'butt', - miterLimit: 10, - strokeNoScale: false, - strokeFirst: false - }, DEFAULT_COMMON_STYLE); - var DEFAULT_PATH_ANIMATION_PROPS = { - style: defaults({ - fill: true, - stroke: true, - strokePercent: true, - fillOpacity: true, - strokeOpacity: true, - lineDashOffset: true, - lineWidth: true, - miterLimit: true - }, DEFAULT_COMMON_ANIMATION_PROPS.style) - }; - var pathCopyParams = TRANSFORMABLE_PROPS.concat(['invisible', 'culling', 'z', 'z2', 'zlevel', 'parent']); - - var Path = function (_super) { - __extends(Path, _super); - - function Path(opts) { - return _super.call(this, opts) || this; - } - - Path.prototype.update = function () { - var _this = this; - - _super.prototype.update.call(this); - - var style = this.style; - - if (style.decal) { - var decalEl = this._decalEl = this._decalEl || new Path(); - - if (decalEl.buildPath === Path.prototype.buildPath) { - decalEl.buildPath = function (ctx) { - _this.buildPath(ctx, _this.shape); - }; - } - - decalEl.silent = true; - var decalElStyle = decalEl.style; - - for (var key in style) { - if (decalElStyle[key] !== style[key]) { - decalElStyle[key] = style[key]; - } - } - - decalElStyle.fill = style.fill ? style.decal : null; - decalElStyle.decal = null; - decalElStyle.shadowColor = null; - style.strokeFirst && (decalElStyle.stroke = null); - - for (var i = 0; i < pathCopyParams.length; ++i) { - decalEl[pathCopyParams[i]] = this[pathCopyParams[i]]; - } - - decalEl.__dirty |= REDRAW_BIT; - } else if (this._decalEl) { - this._decalEl = null; - } - }; - - Path.prototype.getDecalElement = function () { - return this._decalEl; - }; - - Path.prototype._init = function (props) { - var keysArr = keys(props); - this.shape = this.getDefaultShape(); - var defaultStyle = this.getDefaultStyle(); - - if (defaultStyle) { - this.useStyle(defaultStyle); - } - - for (var i = 0; i < keysArr.length; i++) { - var key = keysArr[i]; - var value = props[key]; - - if (key === 'style') { - if (!this.style) { - this.useStyle(value); - } else { - extend(this.style, value); - } - } else if (key === 'shape') { - extend(this.shape, value); - } else { - _super.prototype.attrKV.call(this, key, value); - } - } - - if (!this.style) { - this.useStyle({}); - } - }; - - Path.prototype.getDefaultStyle = function () { - return null; - }; - - Path.prototype.getDefaultShape = function () { - return {}; - }; - - Path.prototype.canBeInsideText = function () { - return this.hasFill(); - }; - - Path.prototype.getInsideTextFill = function () { - var pathFill = this.style.fill; - - if (pathFill !== 'none') { - if (isString(pathFill)) { - var fillLum = lum(pathFill, 0); - - if (fillLum > 0.5) { - return DARK_LABEL_COLOR; - } else if (fillLum > 0.2) { - return LIGHTER_LABEL_COLOR; - } - - return LIGHT_LABEL_COLOR; - } else if (pathFill) { - return LIGHT_LABEL_COLOR; - } - } - - return DARK_LABEL_COLOR; - }; - - Path.prototype.getInsideTextStroke = function (textFill) { - var pathFill = this.style.fill; - - if (isString(pathFill)) { - var zr = this.__zr; - var isDarkMode = !!(zr && zr.isDarkMode()); - var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD; - - if (isDarkMode === isDarkLabel) { - return pathFill; - } - } - }; - - Path.prototype.buildPath = function (ctx, shapeCfg, inBatch) {}; - - Path.prototype.pathUpdated = function () { - this.__dirty &= ~SHAPE_CHANGED_BIT; - }; - - Path.prototype.getUpdatedPathProxy = function (inBatch) { - !this.path && this.createPathProxy(); - this.path.beginPath(); - this.buildPath(this.path, this.shape, inBatch); - return this.path; - }; - - Path.prototype.createPathProxy = function () { - this.path = new PathProxy(false); - }; - - Path.prototype.hasStroke = function () { - var style = this.style; - var stroke = style.stroke; - return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); - }; - - Path.prototype.hasFill = function () { - var style = this.style; - var fill = style.fill; - return fill != null && fill !== 'none'; - }; - - Path.prototype.getBoundingRect = function () { - var rect = this._rect; - var style = this.style; - var needsUpdateRect = !rect; - - if (needsUpdateRect) { - var firstInvoke = false; - - if (!this.path) { - firstInvoke = true; - this.createPathProxy(); - } - - var path = this.path; - - if (firstInvoke || this.__dirty & SHAPE_CHANGED_BIT) { - path.beginPath(); - this.buildPath(path, this.shape, false); - this.pathUpdated(); - } - - rect = path.getBoundingRect(); - } - - this._rect = rect; - - if (this.hasStroke() && this.path && this.path.len() > 0) { - var rectStroke = this._rectStroke || (this._rectStroke = rect.clone()); - - if (this.__dirty || needsUpdateRect) { - rectStroke.copy(rect); - var lineScale = style.strokeNoScale ? this.getLineScale() : 1; - var w = style.lineWidth; - - if (!this.hasFill()) { - var strokeContainThreshold = this.strokeContainThreshold; - w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold); - } - - if (lineScale > 1e-10) { - rectStroke.width += w / lineScale; - rectStroke.height += w / lineScale; - rectStroke.x -= w / lineScale / 2; - rectStroke.y -= w / lineScale / 2; - } - } - - return rectStroke; - } - - return rect; - }; - - Path.prototype.contain = function (x, y) { - var localPos = this.transformCoordToLocal(x, y); - var rect = this.getBoundingRect(); - var style = this.style; - x = localPos[0]; - y = localPos[1]; - - if (rect.contain(x, y)) { - var pathProxy = this.path; - - if (this.hasStroke()) { - var lineWidth = style.lineWidth; - var lineScale = style.strokeNoScale ? this.getLineScale() : 1; - - if (lineScale > 1e-10) { - if (!this.hasFill()) { - lineWidth = Math.max(lineWidth, this.strokeContainThreshold); - } - - if (containStroke(pathProxy, lineWidth / lineScale, x, y)) { - return true; - } - } - } - - if (this.hasFill()) { - return contain$2(pathProxy, x, y); - } - } - - return false; - }; - - Path.prototype.dirtyShape = function () { - this.__dirty |= SHAPE_CHANGED_BIT; - - if (this._rect) { - this._rect = null; - } - - if (this._decalEl) { - this._decalEl.dirtyShape(); - } - - this.markRedraw(); - }; - - Path.prototype.dirty = function () { - this.dirtyStyle(); - this.dirtyShape(); - }; - - Path.prototype.animateShape = function (loop) { - return this.animate('shape', loop); - }; - - Path.prototype.updateDuringAnimation = function (targetKey) { - if (targetKey === 'style') { - this.dirtyStyle(); - } else if (targetKey === 'shape') { - this.dirtyShape(); - } else { - this.markRedraw(); - } - }; - - Path.prototype.attrKV = function (key, value) { - if (key === 'shape') { - this.setShape(value); - } else { - _super.prototype.attrKV.call(this, key, value); - } - }; - - Path.prototype.setShape = function (keyOrObj, value) { - var shape = this.shape; - - if (!shape) { - shape = this.shape = {}; - } - - if (typeof keyOrObj === 'string') { - shape[keyOrObj] = value; - } else { - extend(shape, keyOrObj); - } - - this.dirtyShape(); - return this; - }; - - Path.prototype.shapeChanged = function () { - return !!(this.__dirty & SHAPE_CHANGED_BIT); - }; - - Path.prototype.createStyle = function (obj) { - return createObject(DEFAULT_PATH_STYLE, obj); - }; - - Path.prototype._innerSaveToNormal = function (toState) { - _super.prototype._innerSaveToNormal.call(this, toState); - - var normalState = this._normalState; - - if (toState.shape && !normalState.shape) { - normalState.shape = extend({}, this.shape); - } - }; - - Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { - _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); - - var needsRestoreToNormal = !(state && keepCurrentStates); - var targetShape; - - if (state && state.shape) { - if (transition) { - if (keepCurrentStates) { - targetShape = state.shape; - } else { - targetShape = extend({}, normalState.shape); - extend(targetShape, state.shape); - } - } else { - targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape); - extend(targetShape, state.shape); - } - } else if (needsRestoreToNormal) { - targetShape = normalState.shape; - } - - if (targetShape) { - if (transition) { - this.shape = extend({}, this.shape); - var targetShapePrimaryProps = {}; - var shapeKeys = keys(targetShape); - - for (var i = 0; i < shapeKeys.length; i++) { - var key = shapeKeys[i]; - - if (typeof targetShape[key] === 'object') { - this.shape[key] = targetShape[key]; - } else { - targetShapePrimaryProps[key] = targetShape[key]; - } - } - - this._transitionState(stateName, { - shape: targetShapePrimaryProps - }, animationCfg); - } else { - this.shape = targetShape; - this.dirtyShape(); - } - } - }; - - Path.prototype._mergeStates = function (states) { - var mergedState = _super.prototype._mergeStates.call(this, states); - - var mergedShape; - - for (var i = 0; i < states.length; i++) { - var state = states[i]; - - if (state.shape) { - mergedShape = mergedShape || {}; - - this._mergeStyle(mergedShape, state.shape); - } - } - - if (mergedShape) { - mergedState.shape = mergedShape; - } - - return mergedState; - }; - - Path.prototype.getAnimationStyleProps = function () { - return DEFAULT_PATH_ANIMATION_PROPS; - }; - - Path.prototype.isZeroArea = function () { - return false; - }; - - Path.extend = function (defaultProps) { - var Sub = function (_super) { - __extends(Sub, _super); - - function Sub(opts) { - var _this = _super.call(this, opts) || this; - - defaultProps.init && defaultProps.init.call(_this, opts); - return _this; - } - - Sub.prototype.getDefaultStyle = function () { - return clone$3(defaultProps.style); - }; - - Sub.prototype.getDefaultShape = function () { - return clone$3(defaultProps.shape); - }; - - return Sub; - }(Path); - - for (var key in defaultProps) { - if (typeof defaultProps[key] === 'function') { - Sub.prototype[key] = defaultProps[key]; - } - } - - return Sub; - }; - - Path.initDefaultProps = function () { - var pathProto = Path.prototype; - pathProto.type = 'path'; - pathProto.strokeContainThreshold = 5; - pathProto.segmentIgnoreThreshold = 0; - pathProto.subPixelOptimize = false; - pathProto.autoBatch = false; - pathProto.__dirty = REDRAW_BIT | STYLE_CHANGED_BIT | SHAPE_CHANGED_BIT; - }(); - - return Path; - }(Displayable); - - var DEFAULT_TSPAN_STYLE = defaults({ - strokeFirst: true, - font: DEFAULT_FONT, - x: 0, - y: 0, - textAlign: 'left', - textBaseline: 'top', - miterLimit: 2 - }, DEFAULT_PATH_STYLE); - - var TSpan = function (_super) { - __extends(TSpan, _super); - - function TSpan() { - return _super !== null && _super.apply(this, arguments) || this; - } - - TSpan.prototype.hasStroke = function () { - var style = this.style; - var stroke = style.stroke; - return stroke != null && stroke !== 'none' && style.lineWidth > 0; - }; - - TSpan.prototype.hasFill = function () { - var style = this.style; - var fill = style.fill; - return fill != null && fill !== 'none'; - }; - - TSpan.prototype.createStyle = function (obj) { - return createObject(DEFAULT_TSPAN_STYLE, obj); - }; - - TSpan.prototype.setBoundingRect = function (rect) { - this._rect = rect; - }; - - TSpan.prototype.getBoundingRect = function () { - var style = this.style; - - if (!this._rect) { - var text = style.text; - text != null ? text += '' : text = ''; - var rect = getBoundingRect(text, style.font, style.textAlign, style.textBaseline); - rect.x += style.x || 0; - rect.y += style.y || 0; - - if (this.hasStroke()) { - var w = style.lineWidth; - rect.x -= w / 2; - rect.y -= w / 2; - rect.width += w; - rect.height += w; - } - - this._rect = rect; - } - - return this._rect; - }; - - TSpan.initDefaultProps = function () { - var tspanProto = TSpan.prototype; - tspanProto.dirtyRectTolerance = 10; - }(); - - return TSpan; - }(Displayable); - - TSpan.prototype.type = 'tspan'; - var DEFAULT_IMAGE_STYLE = defaults({ - x: 0, - y: 0 - }, DEFAULT_COMMON_STYLE); - var DEFAULT_IMAGE_ANIMATION_PROPS = { - style: defaults({ - x: true, - y: true, - width: true, - height: true, - sx: true, - sy: true, - sWidth: true, - sHeight: true - }, DEFAULT_COMMON_ANIMATION_PROPS.style) - }; - - function isImageLike$1(source) { - return !!(source && typeof source !== 'string' && source.width && source.height); - } - - var ZRImage = function (_super) { - __extends(ZRImage, _super); - - function ZRImage() { - return _super !== null && _super.apply(this, arguments) || this; - } - - ZRImage.prototype.createStyle = function (obj) { - return createObject(DEFAULT_IMAGE_STYLE, obj); - }; - - ZRImage.prototype._getSize = function (dim) { - var style = this.style; - var size = style[dim]; - - if (size != null) { - return size; - } - - var imageSource = isImageLike$1(style.image) ? style.image : this.__image; - - if (!imageSource) { - return 0; - } - - var otherDim = dim === 'width' ? 'height' : 'width'; - var otherDimSize = style[otherDim]; - - if (otherDimSize == null) { - return imageSource[dim]; - } else { - return imageSource[dim] / imageSource[otherDim] * otherDimSize; - } - }; - - ZRImage.prototype.getWidth = function () { - return this._getSize('width'); - }; - - ZRImage.prototype.getHeight = function () { - return this._getSize('height'); - }; - - ZRImage.prototype.getAnimationStyleProps = function () { - return DEFAULT_IMAGE_ANIMATION_PROPS; - }; - - ZRImage.prototype.getBoundingRect = function () { - var style = this.style; - - if (!this._rect) { - this._rect = new BoundingRect(style.x || 0, style.y || 0, this.getWidth(), this.getHeight()); - } - - return this._rect; - }; - - return ZRImage; - }(Displayable); - - ZRImage.prototype.type = 'image'; - - function buildPath$2(ctx, shape) { - var x = shape.x; - var y = shape.y; - var width = shape.width; - var height = shape.height; - var r = shape.r; - var r1; - var r2; - var r3; - var r4; - - if (width < 0) { - x = x + width; - width = -width; - } - - if (height < 0) { - y = y + height; - height = -height; - } - - if (typeof r === 'number') { - r1 = r2 = r3 = r4 = r; - } else if (r instanceof Array) { - if (r.length === 1) { - r1 = r2 = r3 = r4 = r[0]; - } else if (r.length === 2) { - r1 = r3 = r[0]; - r2 = r4 = r[1]; - } else if (r.length === 3) { - r1 = r[0]; - r2 = r4 = r[1]; - r3 = r[2]; - } else { - r1 = r[0]; - r2 = r[1]; - r3 = r[2]; - r4 = r[3]; - } - } else { - r1 = r2 = r3 = r4 = 0; - } - - var total; - - if (r1 + r2 > width) { - total = r1 + r2; - r1 *= width / total; - r2 *= width / total; - } - - if (r3 + r4 > width) { - total = r3 + r4; - r3 *= width / total; - r4 *= width / total; - } - - if (r2 + r3 > height) { - total = r2 + r3; - r2 *= height / total; - r3 *= height / total; - } - - if (r1 + r4 > height) { - total = r1 + r4; - r1 *= height / total; - r4 *= height / total; - } - - ctx.moveTo(x + r1, y); - ctx.lineTo(x + width - r2, y); - r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0); - ctx.lineTo(x + width, y + height - r3); - r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2); - ctx.lineTo(x + r4, y + height); - r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI); - ctx.lineTo(x, y + r1); - r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5); - } - - var round$1 = Math.round; - - function subPixelOptimizeLine$1(outputShape, inputShape, style) { - if (!inputShape) { - return; - } - - var x1 = inputShape.x1; - var x2 = inputShape.x2; - var y1 = inputShape.y1; - var y2 = inputShape.y2; - outputShape.x1 = x1; - outputShape.x2 = x2; - outputShape.y1 = y1; - outputShape.y2 = y2; - var lineWidth = style && style.lineWidth; - - if (!lineWidth) { - return outputShape; - } - - if (round$1(x1 * 2) === round$1(x2 * 2)) { - outputShape.x1 = outputShape.x2 = subPixelOptimize$1(x1, lineWidth, true); - } - - if (round$1(y1 * 2) === round$1(y2 * 2)) { - outputShape.y1 = outputShape.y2 = subPixelOptimize$1(y1, lineWidth, true); - } - - return outputShape; - } - - function subPixelOptimizeRect$1(outputShape, inputShape, style) { - if (!inputShape) { - return; - } - - var originX = inputShape.x; - var originY = inputShape.y; - var originWidth = inputShape.width; - var originHeight = inputShape.height; - outputShape.x = originX; - outputShape.y = originY; - outputShape.width = originWidth; - outputShape.height = originHeight; - var lineWidth = style && style.lineWidth; - - if (!lineWidth) { - return outputShape; - } - - outputShape.x = subPixelOptimize$1(originX, lineWidth, true); - outputShape.y = subPixelOptimize$1(originY, lineWidth, true); - outputShape.width = Math.max(subPixelOptimize$1(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1); - outputShape.height = Math.max(subPixelOptimize$1(originY + originHeight, lineWidth, false) - outputShape.y, originHeight === 0 ? 0 : 1); - return outputShape; - } - - function subPixelOptimize$1(position, lineWidth, positiveOrNegative) { - if (!lineWidth) { - return position; - } - - var doubledPosition = round$1(position * 2); - return (doubledPosition + round$1(lineWidth)) % 2 === 0 ? doubledPosition / 2 : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; - } - - var RectShape = function () { - function RectShape() { - this.x = 0; - this.y = 0; - this.width = 0; - this.height = 0; - } - - return RectShape; - }(); - - var subPixelOptimizeOutputShape$1 = {}; - - var Rect = function (_super) { - __extends(Rect, _super); - - function Rect(opts) { - return _super.call(this, opts) || this; - } - - Rect.prototype.getDefaultShape = function () { - return new RectShape(); - }; - - Rect.prototype.buildPath = function (ctx, shape) { - var x; - var y; - var width; - var height; - - if (this.subPixelOptimize) { - var optimizedShape = subPixelOptimizeRect$1(subPixelOptimizeOutputShape$1, shape, this.style); - x = optimizedShape.x; - y = optimizedShape.y; - width = optimizedShape.width; - height = optimizedShape.height; - optimizedShape.r = shape.r; - shape = optimizedShape; - } else { - x = shape.x; - y = shape.y; - width = shape.width; - height = shape.height; - } - - if (!shape.r) { - ctx.rect(x, y, width, height); - } else { - buildPath$2(ctx, shape); - } - }; - - Rect.prototype.isZeroArea = function () { - return !this.shape.width || !this.shape.height; - }; - - return Rect; - }(Path); - - Rect.prototype.type = 'rect'; - var DEFAULT_RICH_TEXT_COLOR = { - fill: '#000' - }; - var DEFAULT_STROKE_LINE_WIDTH = 2; - var DEFAULT_TEXT_ANIMATION_PROPS = { - style: defaults({ - fill: true, - stroke: true, - fillOpacity: true, - strokeOpacity: true, - lineWidth: true, - fontSize: true, - lineHeight: true, - width: true, - height: true, - textShadowColor: true, - textShadowBlur: true, - textShadowOffsetX: true, - textShadowOffsetY: true, - backgroundColor: true, - padding: true, - borderColor: true, - borderWidth: true, - borderRadius: true - }, DEFAULT_COMMON_ANIMATION_PROPS.style) - }; - - var ZRText = function (_super) { - __extends(ZRText, _super); - - function ZRText(opts) { - var _this = _super.call(this) || this; - - _this.type = 'text'; - _this._children = []; - _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR; - - _this.attr(opts); - - return _this; - } - - ZRText.prototype.childrenRef = function () { - return this._children; - }; - - ZRText.prototype.update = function () { - _super.prototype.update.call(this); - - if (this.styleChanged()) { - this._updateSubTexts(); - } - - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; - child.zlevel = this.zlevel; - child.z = this.z; - child.z2 = this.z2; - child.culling = this.culling; - child.cursor = this.cursor; - child.invisible = this.invisible; - } - }; - - ZRText.prototype.updateTransform = function () { - var innerTransformable = this.innerTransformable; - - if (innerTransformable) { - innerTransformable.updateTransform(); - - if (innerTransformable.transform) { - this.transform = innerTransformable.transform; - } - } else { - _super.prototype.updateTransform.call(this); - } - }; - - ZRText.prototype.getLocalTransform = function (m) { - var innerTransformable = this.innerTransformable; - return innerTransformable ? innerTransformable.getLocalTransform(m) : _super.prototype.getLocalTransform.call(this, m); - }; - - ZRText.prototype.getComputedTransform = function () { - if (this.__hostTarget) { - this.__hostTarget.getComputedTransform(); - - this.__hostTarget.updateInnerText(true); - } - - return _super.prototype.getComputedTransform.call(this); - }; - - ZRText.prototype._updateSubTexts = function () { - this._childCursor = 0; - normalizeTextStyle(this.style); - this.style.rich ? this._updateRichTexts() : this._updatePlainTexts(); - this._children.length = this._childCursor; - this.styleUpdated(); - }; - - ZRText.prototype.addSelfToZr = function (zr) { - _super.prototype.addSelfToZr.call(this, zr); - - for (var i = 0; i < this._children.length; i++) { - this._children[i].__zr = zr; - } - }; - - ZRText.prototype.removeSelfFromZr = function (zr) { - _super.prototype.removeSelfFromZr.call(this, zr); - - for (var i = 0; i < this._children.length; i++) { - this._children[i].__zr = null; - } - }; - - ZRText.prototype.getBoundingRect = function () { - if (this.styleChanged()) { - this._updateSubTexts(); - } - - if (!this._rect) { - var tmpRect = new BoundingRect(0, 0, 0, 0); - var children = this._children; - var tmpMat = []; - var rect = null; - - for (var i = 0; i < children.length; i++) { - var child = children[i]; - var childRect = child.getBoundingRect(); - var transform = child.getLocalTransform(tmpMat); - - if (transform) { - tmpRect.copy(childRect); - tmpRect.applyTransform(transform); - rect = rect || tmpRect.clone(); - rect.union(tmpRect); - } else { - rect = rect || childRect.clone(); - rect.union(childRect); - } - } - - this._rect = rect || tmpRect; - } - - return this._rect; - }; - - ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) { - this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR; - }; - - ZRText.prototype.setTextContent = function (textContent) { - { - throw new Error('Can\'t attach text on another text'); - } - }; - - ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) { - if (!sourceStyle) { - return targetStyle; - } - - var sourceRich = sourceStyle.rich; - var targetRich = targetStyle.rich || sourceRich && {}; - extend(targetStyle, sourceStyle); - - if (sourceRich && targetRich) { - this._mergeRich(targetRich, sourceRich); - - targetStyle.rich = targetRich; - } else if (targetRich) { - targetStyle.rich = targetRich; - } - - return targetStyle; - }; - - ZRText.prototype._mergeRich = function (targetRich, sourceRich) { - var richNames = keys(sourceRich); - - for (var i = 0; i < richNames.length; i++) { - var richName = richNames[i]; - targetRich[richName] = targetRich[richName] || {}; - extend(targetRich[richName], sourceRich[richName]); - } - }; - - ZRText.prototype.getAnimationStyleProps = function () { - return DEFAULT_TEXT_ANIMATION_PROPS; - }; - - ZRText.prototype._getOrCreateChild = function (Ctor) { - var child = this._children[this._childCursor]; - - if (!child || !(child instanceof Ctor)) { - child = new Ctor(); - } - - this._children[this._childCursor++] = child; - child.__zr = this.__zr; - child.parent = this; - return child; - }; - - ZRText.prototype._updatePlainTexts = function () { - var style = this.style; - var textFont = style.font || DEFAULT_FONT; - var textPadding = style.padding; - var text = getStyleText(style); - var contentBlock = parsePlainText(text, style); - var needDrawBg = needDrawBackground(style); - var bgColorDrawn = !!style.backgroundColor; - var outerHeight = contentBlock.outerHeight; - var outerWidth = contentBlock.outerWidth; - var contentWidth = contentBlock.contentWidth; - var textLines = contentBlock.lines; - var lineHeight = contentBlock.lineHeight; - var defaultStyle = this._defaultStyle; - var baseX = style.x || 0; - var baseY = style.y || 0; - var textAlign = style.align || defaultStyle.align || 'left'; - var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top'; - var textX = baseX; - var textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign); - - if (needDrawBg || textPadding) { - var boxX = adjustTextX(baseX, outerWidth, textAlign); - var boxY = adjustTextY(baseY, outerHeight, verticalAlign); - needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight); - } - - textY += lineHeight / 2; - - if (textPadding) { - textX = getTextXForPadding(baseX, textAlign, textPadding); - - if (verticalAlign === 'top') { - textY += textPadding[0]; - } else if (verticalAlign === 'bottom') { - textY -= textPadding[2]; - } - } - - var defaultLineWidth = 0; - var useDefaultFill = false; - var textFill = getFill('fill' in style ? style.fill : (useDefaultFill = true, defaultStyle.fill)); - var textStroke = getStroke('stroke' in style ? style.stroke : !bgColorDrawn && (!defaultStyle.autoStroke || useDefaultFill) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) : null); - var hasShadow = style.textShadowBlur > 0; - var fixedBoundingRect = style.width != null && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll'); - var calculatedLineHeight = contentBlock.calculatedLineHeight; - - for (var i = 0; i < textLines.length; i++) { - var el = this._getOrCreateChild(TSpan); - - var subElStyle = el.createStyle(); - el.useStyle(subElStyle); - subElStyle.text = textLines[i]; - subElStyle.x = textX; - subElStyle.y = textY; - - if (textAlign) { - subElStyle.textAlign = textAlign; - } - - subElStyle.textBaseline = 'middle'; - subElStyle.opacity = style.opacity; - subElStyle.strokeFirst = true; - - if (hasShadow) { - subElStyle.shadowBlur = style.textShadowBlur || 0; - subElStyle.shadowColor = style.textShadowColor || 'transparent'; - subElStyle.shadowOffsetX = style.textShadowOffsetX || 0; - subElStyle.shadowOffsetY = style.textShadowOffsetY || 0; - } - - subElStyle.stroke = textStroke; - subElStyle.fill = textFill; - - if (textStroke) { - subElStyle.lineWidth = style.lineWidth || defaultLineWidth; - subElStyle.lineDash = style.lineDash; - subElStyle.lineDashOffset = style.lineDashOffset || 0; - } - - subElStyle.font = textFont; - setSeparateFont(subElStyle, style); - textY += lineHeight; - - if (fixedBoundingRect) { - el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), contentWidth, calculatedLineHeight)); - } - } - }; - - ZRText.prototype._updateRichTexts = function () { - var style = this.style; - var text = getStyleText(style); - var contentBlock = parseRichText(text, style); - var contentWidth = contentBlock.width; - var outerWidth = contentBlock.outerWidth; - var outerHeight = contentBlock.outerHeight; - var textPadding = style.padding; - var baseX = style.x || 0; - var baseY = style.y || 0; - var defaultStyle = this._defaultStyle; - var textAlign = style.align || defaultStyle.align; - var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign; - var boxX = adjustTextX(baseX, outerWidth, textAlign); - var boxY = adjustTextY(baseY, outerHeight, verticalAlign); - var xLeft = boxX; - var lineTop = boxY; - - if (textPadding) { - xLeft += textPadding[3]; - lineTop += textPadding[0]; - } - - var xRight = xLeft + contentWidth; - - if (needDrawBackground(style)) { - this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight); - } - - var bgColorDrawn = !!style.backgroundColor; - - for (var i = 0; i < contentBlock.lines.length; i++) { - var line = contentBlock.lines[i]; - var tokens = line.tokens; - var tokenCount = tokens.length; - var lineHeight = line.lineHeight; - var remainedWidth = line.width; - var leftIndex = 0; - var lineXLeft = xLeft; - var lineXRight = xRight; - var rightIndex = tokenCount - 1; - var token = void 0; - - while (leftIndex < tokenCount && (token = tokens[leftIndex], !token.align || token.align === 'left')) { - this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn); - - remainedWidth -= token.width; - lineXLeft += token.width; - leftIndex++; - } - - while (rightIndex >= 0 && (token = tokens[rightIndex], token.align === 'right')) { - this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn); - - remainedWidth -= token.width; - lineXRight -= token.width; - rightIndex--; - } - - lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2; - - while (leftIndex <= rightIndex) { - token = tokens[leftIndex]; - - this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn); - - lineXLeft += token.width; - leftIndex++; - } - - lineTop += lineHeight; - } - }; - - ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) { - var tokenStyle = style.rich[token.styleName] || {}; - tokenStyle.text = token.text; - var verticalAlign = token.verticalAlign; - var y = lineTop + lineHeight / 2; - - if (verticalAlign === 'top') { - y = lineTop + token.height / 2; - } else if (verticalAlign === 'bottom') { - y = lineTop + lineHeight - token.height / 2; - } - - var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle); - needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right' ? x - token.width : textAlign === 'center' ? x - token.width / 2 : x, y - token.height / 2, token.width, token.height); - var bgColorDrawn = !!tokenStyle.backgroundColor; - var textPadding = token.textPadding; - - if (textPadding) { - x = getTextXForPadding(x, textAlign, textPadding); - y -= token.height / 2 - textPadding[0] - token.innerHeight / 2; - } - - var el = this._getOrCreateChild(TSpan); - - var subElStyle = el.createStyle(); - el.useStyle(subElStyle); - var defaultStyle = this._defaultStyle; - var useDefaultFill = false; - var defaultLineWidth = 0; - var textFill = getFill('fill' in tokenStyle ? tokenStyle.fill : 'fill' in style ? style.fill : (useDefaultFill = true, defaultStyle.fill)); - var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke : 'stroke' in style ? style.stroke : !bgColorDrawn && !parentBgColorDrawn && (!defaultStyle.autoStroke || useDefaultFill) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) : null); - var hasShadow = tokenStyle.textShadowBlur > 0 || style.textShadowBlur > 0; - subElStyle.text = token.text; - subElStyle.x = x; - subElStyle.y = y; - - if (hasShadow) { - subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0; - subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent'; - subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0; - subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0; - } - - subElStyle.textAlign = textAlign; - subElStyle.textBaseline = 'middle'; - subElStyle.font = token.font || DEFAULT_FONT; - subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1); - setSeparateFont(subElStyle, tokenStyle); - - if (textStroke) { - subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth); - subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash); - subElStyle.lineDashOffset = style.lineDashOffset || 0; - subElStyle.stroke = textStroke; - } - - if (textFill) { - subElStyle.fill = textFill; - } - - var textWidth = token.contentWidth; - var textHeight = token.contentHeight; - el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight)); - }; - - ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) { - var textBackgroundColor = style.backgroundColor; - var textBorderWidth = style.borderWidth; - var textBorderColor = style.borderColor; - var isImageBg = textBackgroundColor && textBackgroundColor.image; - var isPlainOrGradientBg = textBackgroundColor && !isImageBg; - var textBorderRadius = style.borderRadius; - var self = this; - var rectEl; - var imgEl; - - if (isPlainOrGradientBg || style.lineHeight || textBorderWidth && textBorderColor) { - rectEl = this._getOrCreateChild(Rect); - rectEl.useStyle(rectEl.createStyle()); - rectEl.style.fill = null; - var rectShape = rectEl.shape; - rectShape.x = x; - rectShape.y = y; - rectShape.width = width; - rectShape.height = height; - rectShape.r = textBorderRadius; - rectEl.dirtyShape(); - } - - if (isPlainOrGradientBg) { - var rectStyle = rectEl.style; - rectStyle.fill = textBackgroundColor || null; - rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1); - } else if (isImageBg) { - imgEl = this._getOrCreateChild(ZRImage); - - imgEl.onload = function () { - self.dirtyStyle(); - }; - - var imgStyle = imgEl.style; - imgStyle.image = textBackgroundColor.image; - imgStyle.x = x; - imgStyle.y = y; - imgStyle.width = width; - imgStyle.height = height; - } - - if (textBorderWidth && textBorderColor) { - var rectStyle = rectEl.style; - rectStyle.lineWidth = textBorderWidth; - rectStyle.stroke = textBorderColor; - rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1); - rectStyle.lineDash = style.borderDash; - rectStyle.lineDashOffset = style.borderDashOffset || 0; - rectEl.strokeContainThreshold = 0; - - if (rectEl.hasFill() && rectEl.hasStroke()) { - rectStyle.strokeFirst = true; - rectStyle.lineWidth *= 2; - } - } - - var commonStyle = (rectEl || imgEl).style; - commonStyle.shadowBlur = style.shadowBlur || 0; - commonStyle.shadowColor = style.shadowColor || 'transparent'; - commonStyle.shadowOffsetX = style.shadowOffsetX || 0; - commonStyle.shadowOffsetY = style.shadowOffsetY || 0; - commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1); - }; - - ZRText.makeFont = function (style) { - var font = ''; - - if (hasSeparateFont(style)) { - font = [style.fontStyle, style.fontWeight, parseFontSize(style.fontSize), style.fontFamily || 'sans-serif'].join(' '); - } - - return font && trim(font) || style.textFont || style.font; - }; - - return ZRText; - }(Displayable); - - var VALID_TEXT_ALIGN = { - left: true, - right: 1, - center: 1 - }; - var VALID_TEXT_VERTICAL_ALIGN = { - top: 1, - bottom: 1, - middle: 1 - }; - var FONT_PARTS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily']; - - function parseFontSize(fontSize) { - if (typeof fontSize === 'string' && (fontSize.indexOf('px') !== -1 || fontSize.indexOf('rem') !== -1 || fontSize.indexOf('em') !== -1)) { - return fontSize; - } else if (!isNaN(+fontSize)) { - return fontSize + 'px'; - } else { - return DEFAULT_FONT_SIZE + 'px'; - } - } - - function setSeparateFont(targetStyle, sourceStyle) { - for (var i = 0; i < FONT_PARTS.length; i++) { - var fontProp = FONT_PARTS[i]; - var val = sourceStyle[fontProp]; - - if (val != null) { - targetStyle[fontProp] = val; - } - } - } - - function hasSeparateFont(style) { - return style.fontSize != null || style.fontFamily || style.fontWeight; - } - - function normalizeTextStyle(style) { - normalizeStyle(style); - each$4(style.rich, normalizeStyle); - return style; - } - - function normalizeStyle(style) { - if (style) { - style.font = ZRText.makeFont(style); - var textAlign = style.align; - textAlign === 'middle' && (textAlign = 'center'); - style.align = textAlign == null || VALID_TEXT_ALIGN[textAlign] ? textAlign : 'left'; - var verticalAlign = style.verticalAlign; - verticalAlign === 'center' && (verticalAlign = 'middle'); - style.verticalAlign = verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign] ? verticalAlign : 'top'; - var textPadding = style.padding; - - if (textPadding) { - style.padding = normalizeCssArray$1(style.padding); - } - } - } - - function getStroke(stroke, lineWidth) { - return stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none' ? null : stroke.image || stroke.colorStops ? '#000' : stroke; - } - - function getFill(fill) { - return fill == null || fill === 'none' ? null : fill.image || fill.colorStops ? '#000' : fill; - } - - function getTextXForPadding(x, textAlign, textPadding) { - return textAlign === 'right' ? x - textPadding[1] : textAlign === 'center' ? x + textPadding[3] / 2 - textPadding[1] / 2 : x + textPadding[3]; - } - - function getStyleText(style) { - var text = style.text; - text != null && (text += ''); - return text; - } - - function needDrawBackground(style) { - return !!(style.backgroundColor || style.lineHeight || style.borderWidth && style.borderColor); - } - - var getECData = makeInner(); - - var setCommonECData = function (seriesIndex, dataType, dataIdx, el) { - if (el) { - var ecData = getECData(el); // Add data index and series index for indexing the data by element - // Useful in tooltip - - ecData.dataIndex = dataIdx; - ecData.dataType = dataType; - ecData.seriesIndex = seriesIndex; - ecData.ssrType = 'chart'; // TODO: not store dataIndex on children. - - if (el.type === 'group') { - el.traverse(function (child) { - var childECData = getECData(child); - childECData.seriesIndex = seriesIndex; - childECData.dataIndex = dataIdx; - childECData.dataType = dataType; - childECData.ssrType = 'chart'; - }); - } - } - }; // Reserve 0 as default. - - - var _highlightNextDigit = 1; - var _highlightKeyMap = {}; - var getSavedStates = makeInner(); - var getComponentStates = makeInner(); - var HOVER_STATE_NORMAL = 0; - var HOVER_STATE_BLUR = 1; - var HOVER_STATE_EMPHASIS = 2; - var SPECIAL_STATES = ['emphasis', 'blur', 'select']; - var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select']; - var Z2_EMPHASIS_LIFT = 10; - var Z2_SELECT_LIFT = 9; - var HIGHLIGHT_ACTION_TYPE = 'highlight'; - var DOWNPLAY_ACTION_TYPE = 'downplay'; - var SELECT_ACTION_TYPE = 'select'; - var UNSELECT_ACTION_TYPE = 'unselect'; - var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect'; - - function hasFillOrStroke(fillOrStroke) { - return fillOrStroke != null && fillOrStroke !== 'none'; - } - - function doChangeHoverState(el, stateName, hoverStateEnum) { - if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) { - el.onHoverStateChange(stateName); - } - - el.hoverState = hoverStateEnum; - } - - function singleEnterEmphasis(el) { - // Only mark the flag. - // States will be applied in the echarts.ts in next frame. - doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS); - } - - function singleLeaveEmphasis(el) { - // Only mark the flag. - // States will be applied in the echarts.ts in next frame. - if (el.hoverState === HOVER_STATE_EMPHASIS) { - doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); - } - } - - function singleEnterBlur(el) { - doChangeHoverState(el, 'blur', HOVER_STATE_BLUR); - } - - function singleLeaveBlur(el) { - if (el.hoverState === HOVER_STATE_BLUR) { - doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); - } - } - - function singleEnterSelect(el) { - el.selected = true; - } - - function singleLeaveSelect(el) { - el.selected = false; - } - - function updateElementState(el, updater, commonParam) { - updater(el, commonParam); - } - - function traverseUpdateState(el, updater, commonParam) { - updateElementState(el, updater, commonParam); - el.isGroup && el.traverse(function (child) { - updateElementState(child, updater, commonParam); - }); - } - - function setStatesFlag(el, stateName) { - switch (stateName) { - case 'emphasis': - el.hoverState = HOVER_STATE_EMPHASIS; - break; - - case 'normal': - el.hoverState = HOVER_STATE_NORMAL; - break; - - case 'blur': - el.hoverState = HOVER_STATE_BLUR; - break; - - case 'select': - el.selected = true; - } - } - - function getFromStateStyle(el, props, toStateName, defaultValue) { - var style = el.style; - var fromState = {}; - - for (var i = 0; i < props.length; i++) { - var propName = props[i]; - var val = style[propName]; - fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val; - } - - for (var i = 0; i < el.animators.length; i++) { - var animator = el.animators[i]; - - if (animator.__fromStateTransition // Don't consider the animation to emphasis state. - && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') { - animator.saveTo(fromState, props); - } - } - - return fromState; - } - - function createEmphasisDefaultState(el, stateName, targetStates, state) { - var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0; - var cloned = false; - - if (el instanceof Path) { - var store = getSavedStates(el); - var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill; - var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke; - - if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) { - state = state || {}; - var emphasisStyle = state.style || {}; // inherit case - - if (emphasisStyle.fill === 'inherit') { - cloned = true; - state = extend({}, state); - emphasisStyle = extend({}, emphasisStyle); - emphasisStyle.fill = fromFill; - } // Apply default color lift - else if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) { - cloned = true; // Not modify the original value. - - state = extend({}, state); - emphasisStyle = extend({}, emphasisStyle); // Already being applied 'emphasis'. DON'T lift color multiple times. - - emphasisStyle.fill = liftColor(fromFill); - } // Not highlight stroke if fill has been highlighted. - else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) { - if (!cloned) { - state = extend({}, state); - emphasisStyle = extend({}, emphasisStyle); - } - - emphasisStyle.stroke = liftColor(fromStroke); - } - - state.style = emphasisStyle; - } - } - - if (state) { - // TODO Share with textContent? - if (state.z2 == null) { - if (!cloned) { - state = extend({}, state); - } - - var z2EmphasisLift = el.z2EmphasisLift; - state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT); - } - } - - return state; - } - - function createSelectDefaultState(el, stateName, state) { - // const hasSelect = indexOf(el.currentStates, stateName) >= 0; - if (state) { - // TODO Share with textContent? - if (state.z2 == null) { - state = extend({}, state); - var z2SelectLift = el.z2SelectLift; - state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT); - } - } - - return state; - } - - function createBlurDefaultState(el, stateName, state) { - var hasBlur = indexOf(el.currentStates, stateName) >= 0; - var currentOpacity = el.style.opacity; - var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, { - opacity: 1 - }) : null; - state = state || {}; - var blurStyle = state.style || {}; - - if (blurStyle.opacity == null) { - // clone state - state = extend({}, state); - blurStyle = extend({ - // Already being applied 'emphasis'. DON'T mul opacity multiple times. - opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1 - }, blurStyle); - state.style = blurStyle; - } - - return state; - } - - function elementStateProxy(stateName, targetStates) { - var state = this.states[stateName]; - - if (this.style) { - if (stateName === 'emphasis') { - return createEmphasisDefaultState(this, stateName, targetStates, state); - } else if (stateName === 'blur') { - return createBlurDefaultState(this, stateName, state); - } else if (stateName === 'select') { - return createSelectDefaultState(this, stateName, state); - } - } - - return state; - } - /** - * Set hover style (namely "emphasis style") of element. - * @param el Should not be `zrender/graphic/Group`. - * @param focus 'self' | 'selfInSeries' | 'series' - */ - - - function setDefaultStateProxy(el) { - el.stateProxy = elementStateProxy; - var textContent = el.getTextContent(); - var textGuide = el.getTextGuideLine(); - - if (textContent) { - textContent.stateProxy = elementStateProxy; - } - - if (textGuide) { - textGuide.stateProxy = elementStateProxy; - } - } - - function enterEmphasisWhenMouseOver(el, e) { - !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight. - && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis); - } - - function leaveEmphasisWhenMouseOut(el, e) { - !shouldSilent(el, e) // "emphasis" event highlight has higher priority than mouse highlight. - && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis); - } - - function enterEmphasis(el, highlightDigit) { - el.__highByOuter |= 1 << (highlightDigit || 0); - traverseUpdateState(el, singleEnterEmphasis); - } - - function leaveEmphasis(el, highlightDigit) { - !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis); - } - - function enterBlur(el) { - traverseUpdateState(el, singleEnterBlur); - } - - function leaveBlur(el) { - traverseUpdateState(el, singleLeaveBlur); - } - - function enterSelect(el) { - traverseUpdateState(el, singleEnterSelect); - } - - function leaveSelect(el) { - traverseUpdateState(el, singleLeaveSelect); - } - - function shouldSilent(el, e) { - return el.__highDownSilentOnTouch && e.zrByTouch; - } - - function allLeaveBlur(api) { - var model = api.getModel(); - var leaveBlurredSeries = []; - var allComponentViews = []; - model.eachComponent(function (componentType, componentModel) { - var componentStates = getComponentStates(componentModel); - var isSeries = componentType === 'series'; - var view = isSeries ? api.getViewOfSeriesModel(componentModel) : api.getViewOfComponentModel(componentModel); - !isSeries && allComponentViews.push(view); - - if (componentStates.isBlured) { - // Leave blur anyway - view.group.traverse(function (child) { - singleLeaveBlur(child); - }); - isSeries && leaveBlurredSeries.push(componentModel); - } - - componentStates.isBlured = false; - }); - each$4(allComponentViews, function (view) { - if (view && view.toggleBlurSeries) { - view.toggleBlurSeries(leaveBlurredSeries, false, model); - } - }); - } - - function blurSeries(targetSeriesIndex, focus, blurScope, api) { - var ecModel = api.getModel(); - blurScope = blurScope || 'coordinateSystem'; - - function leaveBlurOfIndices(data, dataIndices) { - for (var i = 0; i < dataIndices.length; i++) { - var itemEl = data.getItemGraphicEl(dataIndices[i]); - itemEl && leaveBlur(itemEl); - } - } - - if (targetSeriesIndex == null) { - return; - } - - if (!focus || focus === 'none') { - return; - } - - var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex); - var targetCoordSys = targetSeriesModel.coordinateSystem; - - if (targetCoordSys && targetCoordSys.master) { - targetCoordSys = targetCoordSys.master; - } - - var blurredSeries = []; - ecModel.eachSeries(function (seriesModel) { - var sameSeries = targetSeriesModel === seriesModel; - var coordSys = seriesModel.coordinateSystem; - - if (coordSys && coordSys.master) { - coordSys = coordSys.master; - } - - var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries; // If there is no coordinate system. use sameSeries instead. - - if (!( // Not blur other series if blurScope series - blurScope === 'series' && !sameSeries // Not blur other coordinate system if blurScope is coordinateSystem - || blurScope === 'coordinateSystem' && !sameCoordSys // Not blur self series if focus is series. - || focus === 'series' && sameSeries // TODO blurScope: coordinate system - )) { - var view = api.getViewOfSeriesModel(seriesModel); - view.group.traverse(function (child) { - // For the elements that have been triggered by other components, - // and are still required to be highlighted, - // because the current is directly forced to blur the element, - // it will cause the focus self to be unable to highlight, so skip the blur of this element. - if (child.__highByOuter && sameSeries && focus === 'self') { - return; - } - - singleEnterBlur(child); - }); - - if (isArrayLike(focus)) { - leaveBlurOfIndices(seriesModel.getData(), focus); - } else if (isObject$2(focus)) { - var dataTypes = keys(focus); - - for (var d = 0; d < dataTypes.length; d++) { - leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]); - } - } - - blurredSeries.push(seriesModel); - getComponentStates(seriesModel).isBlured = true; - } - }); - ecModel.eachComponent(function (componentType, componentModel) { - if (componentType === 'series') { - return; - } - - var view = api.getViewOfComponentModel(componentModel); - - if (view && view.toggleBlurSeries) { - view.toggleBlurSeries(blurredSeries, true, ecModel); - } - }); - } - - function blurComponent(componentMainType, componentIndex, api) { - if (componentMainType == null || componentIndex == null) { - return; - } - - var componentModel = api.getModel().getComponent(componentMainType, componentIndex); - - if (!componentModel) { - return; - } - - getComponentStates(componentModel).isBlured = true; - var view = api.getViewOfComponentModel(componentModel); - - if (!view || !view.focusBlurEnabled) { - return; - } - - view.group.traverse(function (child) { - singleEnterBlur(child); - }); - } - - function blurSeriesFromHighlightPayload(seriesModel, payload, api) { - var seriesIndex = seriesModel.seriesIndex; - var data = seriesModel.getData(payload.dataType); - - if (!data) { - { - error("Unknown dataType " + payload.dataType); - } - return; - } - - var dataIndex = queryDataIndex(data, payload); // Pick the first one if there is multiple/none exists. - - dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0; - var el = data.getItemGraphicEl(dataIndex); - - if (!el) { - var count = data.count(); - var current = 0; // If data on dataIndex is NaN. - - while (!el && current < count) { - el = data.getItemGraphicEl(current++); - } - } - - if (el) { - var ecData = getECData(el); - blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api); - } else { - // If there is no element put on the data. Try getting it from raw option - // TODO Should put it on seriesModel? - var focus_1 = seriesModel.get(['emphasis', 'focus']); - var blurScope = seriesModel.get(['emphasis', 'blurScope']); - - if (focus_1 != null) { - blurSeries(seriesIndex, focus_1, blurScope, api); - } - } - } - - function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) { - var ret = { - focusSelf: false, - dispatchers: null - }; - - if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) { - return ret; - } - - var componentModel = api.getModel().getComponent(componentMainType, componentIndex); - - if (!componentModel) { - return ret; - } - - var view = api.getViewOfComponentModel(componentModel); - - if (!view || !view.findHighDownDispatchers) { - return ret; - } - - var dispatchers = view.findHighDownDispatchers(name); // At presnet, the component (like Geo) only blur inside itself. - // So we do not use `blurScope` in component. - - var focusSelf; - - for (var i = 0; i < dispatchers.length; i++) { - if (!isHighDownDispatcher(dispatchers[i])) { - error('param should be highDownDispatcher'); - } - - if (getECData(dispatchers[i]).focus === 'self') { - focusSelf = true; - break; - } - } - - return { - focusSelf: focusSelf, - dispatchers: dispatchers - }; - } - - function handleGlobalMouseOverForHighDown(dispatcher, e, api) { - if (!isHighDownDispatcher(dispatcher)) { - error('param should be highDownDispatcher'); - } - - var ecData = getECData(dispatcher); - - var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api), - dispatchers = _a.dispatchers, - focusSelf = _a.focusSelf; // If `findHighDownDispatchers` is supported on the component, - // highlight/downplay elements with the same name. - - - if (dispatchers) { - if (focusSelf) { - blurComponent(ecData.componentMainType, ecData.componentIndex, api); - } - - each$4(dispatchers, function (dispatcher) { - return enterEmphasisWhenMouseOver(dispatcher, e); - }); - } else { - // Try blur all in the related series. Then emphasis the hoverred. - // TODO. progressive mode. - blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api); - - if (ecData.focus === 'self') { - blurComponent(ecData.componentMainType, ecData.componentIndex, api); - } // Other than series, component that not support `findHighDownDispatcher` will - // also use it. But in this case, highlight/downplay are only supported in - // mouse hover but not in dispatchAction. - - - enterEmphasisWhenMouseOver(dispatcher, e); - } - } - - function handleGlobalMouseOutForHighDown(dispatcher, e, api) { - if (!isHighDownDispatcher(dispatcher)) { - error('param should be highDownDispatcher'); - } - - allLeaveBlur(api); - var ecData = getECData(dispatcher); - var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers; - - if (dispatchers) { - each$4(dispatchers, function (dispatcher) { - return leaveEmphasisWhenMouseOut(dispatcher, e); - }); - } else { - leaveEmphasisWhenMouseOut(dispatcher, e); - } - } - - function toggleSelectionFromPayload(seriesModel, payload, api) { - if (!isSelectChangePayload(payload)) { - return; - } - - var dataType = payload.dataType; - var data = seriesModel.getData(dataType); - var dataIndex = queryDataIndex(data, payload); - - if (!isArray(dataIndex)) { - dataIndex = [dataIndex]; - } - - seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType); - } - - function updateSeriesElementSelection(seriesModel) { - var allData = seriesModel.getAllData(); - each$4(allData, function (_a) { - var data = _a.data, - type = _a.type; - data.eachItemGraphicEl(function (el, idx) { - seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el); - }); - }); - } - - function getAllSelectedIndices(ecModel) { - var ret = []; - ecModel.eachSeries(function (seriesModel) { - var allData = seriesModel.getAllData(); - each$4(allData, function (_a) { - _a.data; - var type = _a.type; - var dataIndices = seriesModel.getSelectedDataIndices(); - - if (dataIndices.length > 0) { - var item = { - dataIndex: dataIndices, - seriesIndex: seriesModel.seriesIndex - }; - - if (type != null) { - item.dataType = type; - } - - ret.push(item); - } - }); - }); - return ret; - } - /** - * Enable the function that mouseover will trigger the emphasis state. - * - * NOTE: - * This function should be used on the element with dataIndex, seriesIndex. - * - */ - - - function enableHoverEmphasis(el, focus, blurScope) { - setAsHighDownDispatcher(el, true); - traverseUpdateState(el, setDefaultStateProxy); - enableHoverFocus(el, focus, blurScope); - } - - function disableHoverEmphasis(el) { - setAsHighDownDispatcher(el, false); - } - - function toggleHoverEmphasis(el, focus, blurScope, isDisabled) { - isDisabled ? disableHoverEmphasis(el) : enableHoverEmphasis(el, focus, blurScope); - } - - function enableHoverFocus(el, focus, blurScope) { - var ecData = getECData(el); - - if (focus != null) { - // TODO dataIndex may be set after this function. This check is not useful. - // if (ecData.dataIndex == null) { - // if (__DEV__) { - // console.warn('focus can only been set on element with dataIndex'); - // } - // } - // else { - ecData.focus = focus; - ecData.blurScope = blurScope; // } - } else if (ecData.focus) { - ecData.focus = null; - } - } - - var OTHER_STATES = ['emphasis', 'blur', 'select']; - var defaultStyleGetterMap = { - itemStyle: 'getItemStyle', - lineStyle: 'getLineStyle', - areaStyle: 'getAreaStyle' - }; - /** - * Set emphasis/blur/selected states of element. - */ - - function setStatesStylesFromModel(el, itemModel, styleType, // default itemStyle - getter) { - styleType = styleType || 'itemStyle'; - - for (var i = 0; i < OTHER_STATES.length; i++) { - var stateName = OTHER_STATES[i]; - var model = itemModel.getModel([stateName, styleType]); - var state = el.ensureState(stateName); // Let it throw error if getterType is not found. - - state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]](); - } - } - /** - * - * Set element as highlight / downplay dispatcher. - * It will be checked when element received mouseover event or from highlight action. - * It's in change of all highlight/downplay behavior of it's children. - * - * @param el - * @param el.highDownSilentOnTouch - * In touch device, mouseover event will be trigger on touchstart event - * (see module:zrender/dom/HandlerProxy). By this mechanism, we can - * conveniently use hoverStyle when tap on touch screen without additional - * code for compatibility. - * But if the chart/component has select feature, which usually also use - * hoverStyle, there might be conflict between 'select-highlight' and - * 'hover-highlight' especially when roam is enabled (see geo for example). - * In this case, `highDownSilentOnTouch` should be used to disable - * hover-highlight on touch device. - * @param asDispatcher If `false`, do not set as "highDownDispatcher". - */ - - - function setAsHighDownDispatcher(el, asDispatcher) { - var disable = asDispatcher === false; - var extendedEl = el; // Make `highDownSilentOnTouch` and `onStateChange` only work after - // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly. - - if (el.highDownSilentOnTouch) { - extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch; - } // Simple optimize, since this method might be - // called for each elements of a group in some cases. - - - if (!disable || extendedEl.__highDownDispatcher) { - // Emphasis, normal can be triggered manually by API or other components like hover link. - // el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent); - // Also keep previous record. - extendedEl.__highByOuter = extendedEl.__highByOuter || 0; - extendedEl.__highDownDispatcher = !disable; - } - } - - function isHighDownDispatcher(el) { - return !!(el && el.__highDownDispatcher); - } - /** - * Support highlight/downplay record on each elements. - * For the case: hover highlight/downplay (legend, visualMap, ...) and - * user triggered highlight/downplay should not conflict. - * Only all of the highlightDigit cleared, return to normal. - * @param {string} highlightKey - * @return {number} highlightDigit - */ - - - function getHighlightDigit(highlightKey) { - var highlightDigit = _highlightKeyMap[highlightKey]; - - if (highlightDigit == null && _highlightNextDigit <= 32) { - highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++; - } - - return highlightDigit; - } - - function isSelectChangePayload(payload) { - var payloadType = payload.type; - return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE; - } - - function isHighDownPayload(payload) { - var payloadType = payload.type; - return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE; - } - - function savePathStates(el) { - var store = getSavedStates(el); - store.normalFill = el.style.fill; - store.normalStroke = el.style.stroke; - var selectState = el.states.select || {}; - store.selectFill = selectState.style && selectState.style.fill || null; - store.selectStroke = selectState.style && selectState.style.stroke || null; - } - - var CMD$1 = PathProxy.CMD; - var points = [[], [], []]; - var mathSqrt$2 = Math.sqrt; - var mathAtan2 = Math.atan2; - - function transformPath(path, m) { - if (!m) { - return; - } - - var data = path.data; - var len = path.len(); - var cmd; - var nPoint; - var i; - var j; - var k; - var p; - var M = CMD$1.M; - var C = CMD$1.C; - var L = CMD$1.L; - var R = CMD$1.R; - var A = CMD$1.A; - var Q = CMD$1.Q; - - for (i = 0, j = 0; i < len;) { - cmd = data[i++]; - j = i; - nPoint = 0; - - switch (cmd) { - case M: - nPoint = 1; - break; - - case L: - nPoint = 1; - break; - - case C: - nPoint = 3; - break; - - case Q: - nPoint = 2; - break; - - case A: - var x = m[4]; - var y = m[5]; - var sx = mathSqrt$2(m[0] * m[0] + m[1] * m[1]); - var sy = mathSqrt$2(m[2] * m[2] + m[3] * m[3]); - var angle = mathAtan2(-m[1] / sy, m[0] / sx); - data[i] *= sx; - data[i++] += x; - data[i] *= sy; - data[i++] += y; - data[i++] *= sx; - data[i++] *= sy; - data[i++] += angle; - data[i++] += angle; - i += 2; - j = i; - break; - - case R: - p[0] = data[i++]; - p[1] = data[i++]; - applyTransform$1(p, p, m); - data[j++] = p[0]; - data[j++] = p[1]; - p[0] += data[i++]; - p[1] += data[i++]; - applyTransform$1(p, p, m); - data[j++] = p[0]; - data[j++] = p[1]; - } - - for (k = 0; k < nPoint; k++) { - var p_1 = points[k]; - p_1[0] = data[i++]; - p_1[1] = data[i++]; - applyTransform$1(p_1, p_1, m); - data[j++] = p_1[0]; - data[j++] = p_1[1]; - } - } - - path.increaseVersion(); - } - - var mathSqrt$1 = Math.sqrt; - var mathSin$2 = Math.sin; - var mathCos$2 = Math.cos; - var PI$4 = Math.PI; - - function vMag(v) { - return Math.sqrt(v[0] * v[0] + v[1] * v[1]); - } - - function vRatio(u, v) { - return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); - } - - function vAngle(u, v) { - return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v)); - } - - function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) { - var psi = psiDeg * (PI$4 / 180.0); - var xp = mathCos$2(psi) * (x1 - x2) / 2.0 + mathSin$2(psi) * (y1 - y2) / 2.0; - var yp = -1 * mathSin$2(psi) * (x1 - x2) / 2.0 + mathCos$2(psi) * (y1 - y2) / 2.0; - var lambda = xp * xp / (rx * rx) + yp * yp / (ry * ry); - - if (lambda > 1) { - rx *= mathSqrt$1(lambda); - ry *= mathSqrt$1(lambda); - } - - var f = (fa === fs ? -1 : 1) * mathSqrt$1((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (yp * yp) + ry * ry * (xp * xp))) || 0; - var cxp = f * rx * yp / ry; - var cyp = f * -ry * xp / rx; - var cx = (x1 + x2) / 2.0 + mathCos$2(psi) * cxp - mathSin$2(psi) * cyp; - var cy = (y1 + y2) / 2.0 + mathSin$2(psi) * cxp + mathCos$2(psi) * cyp; - var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); - var u = [(xp - cxp) / rx, (yp - cyp) / ry]; - var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; - var dTheta = vAngle(u, v); - - if (vRatio(u, v) <= -1) { - dTheta = PI$4; - } - - if (vRatio(u, v) >= 1) { - dTheta = 0; - } - - if (dTheta < 0) { - var n = Math.round(dTheta / PI$4 * 1e6) / 1e6; - dTheta = PI$4 * 2 + n % 2 * PI$4; - } - - path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs); - } - - var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig; - var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; - - function createPathProxyFromString(data) { - var path = new PathProxy(); - - if (!data) { - return path; - } - - var cpx = 0; - var cpy = 0; - var subpathX = cpx; - var subpathY = cpy; - var prevCmd; - var CMD = PathProxy.CMD; - var cmdList = data.match(commandReg); - - if (!cmdList) { - return path; - } - - for (var l = 0; l < cmdList.length; l++) { - var cmdText = cmdList[l]; - var cmdStr = cmdText.charAt(0); - var cmd = void 0; - var p = cmdText.match(numberReg) || []; - var pLen = p.length; - - for (var i = 0; i < pLen; i++) { - p[i] = parseFloat(p[i]); - } - - var off = 0; - - while (off < pLen) { - var ctlPtx = void 0; - var ctlPty = void 0; - var rx = void 0; - var ry = void 0; - var psi = void 0; - var fa = void 0; - var fs = void 0; - var x1 = cpx; - var y1 = cpy; - var len = void 0; - var pathData = void 0; - - switch (cmdStr) { - case 'l': - cpx += p[off++]; - cpy += p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'L': - cpx = p[off++]; - cpy = p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'm': - cpx += p[off++]; - cpy += p[off++]; - cmd = CMD.M; - path.addData(cmd, cpx, cpy); - subpathX = cpx; - subpathY = cpy; - cmdStr = 'l'; - break; - - case 'M': - cpx = p[off++]; - cpy = p[off++]; - cmd = CMD.M; - path.addData(cmd, cpx, cpy); - subpathX = cpx; - subpathY = cpy; - cmdStr = 'L'; - break; - - case 'h': - cpx += p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'H': - cpx = p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'v': - cpy += p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'V': - cpy = p[off++]; - cmd = CMD.L; - path.addData(cmd, cpx, cpy); - break; - - case 'C': - cmd = CMD.C; - path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]); - cpx = p[off - 2]; - cpy = p[off - 1]; - break; - - case 'c': - cmd = CMD.C; - path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy); - cpx += p[off - 2]; - cpy += p[off - 1]; - break; - - case 'S': - ctlPtx = cpx; - ctlPty = cpy; - len = path.len(); - pathData = path.data; - - if (prevCmd === CMD.C) { - ctlPtx += cpx - pathData[len - 4]; - ctlPty += cpy - pathData[len - 3]; - } - - cmd = CMD.C; - x1 = p[off++]; - y1 = p[off++]; - cpx = p[off++]; - cpy = p[off++]; - path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); - break; - - case 's': - ctlPtx = cpx; - ctlPty = cpy; - len = path.len(); - pathData = path.data; - - if (prevCmd === CMD.C) { - ctlPtx += cpx - pathData[len - 4]; - ctlPty += cpy - pathData[len - 3]; - } - - cmd = CMD.C; - x1 = cpx + p[off++]; - y1 = cpy + p[off++]; - cpx += p[off++]; - cpy += p[off++]; - path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); - break; - - case 'Q': - x1 = p[off++]; - y1 = p[off++]; - cpx = p[off++]; - cpy = p[off++]; - cmd = CMD.Q; - path.addData(cmd, x1, y1, cpx, cpy); - break; - - case 'q': - x1 = p[off++] + cpx; - y1 = p[off++] + cpy; - cpx += p[off++]; - cpy += p[off++]; - cmd = CMD.Q; - path.addData(cmd, x1, y1, cpx, cpy); - break; - - case 'T': - ctlPtx = cpx; - ctlPty = cpy; - len = path.len(); - pathData = path.data; - - if (prevCmd === CMD.Q) { - ctlPtx += cpx - pathData[len - 4]; - ctlPty += cpy - pathData[len - 3]; - } - - cpx = p[off++]; - cpy = p[off++]; - cmd = CMD.Q; - path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); - break; - - case 't': - ctlPtx = cpx; - ctlPty = cpy; - len = path.len(); - pathData = path.data; - - if (prevCmd === CMD.Q) { - ctlPtx += cpx - pathData[len - 4]; - ctlPty += cpy - pathData[len - 3]; - } - - cpx += p[off++]; - cpy += p[off++]; - cmd = CMD.Q; - path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); - break; - - case 'A': - rx = p[off++]; - ry = p[off++]; - psi = p[off++]; - fa = p[off++]; - fs = p[off++]; - x1 = cpx, y1 = cpy; - cpx = p[off++]; - cpy = p[off++]; - cmd = CMD.A; - processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); - break; - - case 'a': - rx = p[off++]; - ry = p[off++]; - psi = p[off++]; - fa = p[off++]; - fs = p[off++]; - x1 = cpx, y1 = cpy; - cpx += p[off++]; - cpy += p[off++]; - cmd = CMD.A; - processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); - break; - } - } - - if (cmdStr === 'z' || cmdStr === 'Z') { - cmd = CMD.Z; - path.addData(cmd); - cpx = subpathX; - cpy = subpathY; - } - - prevCmd = cmd; - } - - path.toStatic(); - return path; - } - - var SVGPath = function (_super) { - __extends(SVGPath, _super); - - function SVGPath() { - return _super !== null && _super.apply(this, arguments) || this; - } - - SVGPath.prototype.applyTransform = function (m) {}; - - return SVGPath; - }(Path); - - function isPathProxy(path) { - return path.setData != null; - } - - function createPathOptions(str, opts) { - var pathProxy = createPathProxyFromString(str); - var innerOpts = extend({}, opts); - - innerOpts.buildPath = function (path) { - if (isPathProxy(path)) { - path.setData(pathProxy.data); - var ctx = path.getContext(); - - if (ctx) { - path.rebuildPath(ctx, 1); - } - } else { - var ctx = path; - pathProxy.rebuildPath(ctx, 1); - } - }; - - innerOpts.applyTransform = function (m) { - transformPath(pathProxy, m); - this.dirtyShape(); - }; - - return innerOpts; - } - - function createFromString(str, opts) { - return new SVGPath(createPathOptions(str, opts)); - } - - function extendFromString(str, defaultOpts) { - var innerOpts = createPathOptions(str, defaultOpts); - - var Sub = function (_super) { - __extends(Sub, _super); - - function Sub(opts) { - var _this = _super.call(this, opts) || this; - - _this.applyTransform = innerOpts.applyTransform; - _this.buildPath = innerOpts.buildPath; - return _this; - } - - return Sub; - }(SVGPath); - - return Sub; - } - - function mergePath$1(pathEls, opts) { - var pathList = []; - var len = pathEls.length; - - for (var i = 0; i < len; i++) { - var pathEl = pathEls[i]; - pathList.push(pathEl.getUpdatedPathProxy(true)); - } - - var pathBundle = new Path(opts); - pathBundle.createPathProxy(); - - pathBundle.buildPath = function (path) { - if (isPathProxy(path)) { - path.appendPath(pathList); - var ctx = path.getContext(); - - if (ctx) { - path.rebuildPath(ctx, 1); - } - } - }; - - return pathBundle; - } - - var CircleShape = function () { - function CircleShape() { - this.cx = 0; - this.cy = 0; - this.r = 0; - } - - return CircleShape; - }(); - - var Circle = function (_super) { - __extends(Circle, _super); - - function Circle(opts) { - return _super.call(this, opts) || this; - } - - Circle.prototype.getDefaultShape = function () { - return new CircleShape(); - }; - - Circle.prototype.buildPath = function (ctx, shape) { - ctx.moveTo(shape.cx + shape.r, shape.cy); - ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2); - }; - - return Circle; - }(Path); - - Circle.prototype.type = 'circle'; - - var EllipseShape = function () { - function EllipseShape() { - this.cx = 0; - this.cy = 0; - this.rx = 0; - this.ry = 0; - } - - return EllipseShape; - }(); - - var Ellipse = function (_super) { - __extends(Ellipse, _super); - - function Ellipse(opts) { - return _super.call(this, opts) || this; - } - - Ellipse.prototype.getDefaultShape = function () { - return new EllipseShape(); - }; - - Ellipse.prototype.buildPath = function (ctx, shape) { - var k = 0.5522848; - var x = shape.cx; - var y = shape.cy; - var a = shape.rx; - var b = shape.ry; - var ox = a * k; - var oy = b * k; - ctx.moveTo(x - a, y); - ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b); - ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y); - ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b); - ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y); - ctx.closePath(); - }; - - return Ellipse; - }(Path); - - Ellipse.prototype.type = 'ellipse'; - var PI$3 = Math.PI; - var PI2$3 = PI$3 * 2; - var mathSin$1 = Math.sin; - var mathCos$1 = Math.cos; - var mathACos = Math.acos; - var mathATan2 = Math.atan2; - var mathAbs = Math.abs; - var mathSqrt = Math.sqrt; - var mathMax$3 = Math.max; - var mathMin$3 = Math.min; - var e = 1e-4; - - function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { - var dx10 = x1 - x0; - var dy10 = y1 - y0; - var dx32 = x3 - x2; - var dy32 = y3 - y2; - var t = dy32 * dx10 - dx32 * dy10; - - if (t * t < e) { - return; - } - - t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t; - return [x0 + t * dx10, y0 + t * dy10]; - } - - function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) { - var x01 = x0 - x1; - var y01 = y0 - y1; - var lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01); - var ox = lo * y01; - var oy = -lo * x01; - var x11 = x0 + ox; - var y11 = y0 + oy; - var x10 = x1 + ox; - var y10 = y1 + oy; - var x00 = (x11 + x10) / 2; - var y00 = (y11 + y10) / 2; - var dx = x10 - x11; - var dy = y10 - y11; - var d2 = dx * dx + dy * dy; - var r = radius - cr; - var s = x11 * y10 - x10 * y11; - var d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax$3(0, r * r * d2 - s * s)); - var cx0 = (s * dy - dx * d) / d2; - var cy0 = (-s * dx - dy * d) / d2; - var cx1 = (s * dy + dx * d) / d2; - var cy1 = (-s * dx + dy * d) / d2; - var dx0 = cx0 - x00; - var dy0 = cy0 - y00; - var dx1 = cx1 - x00; - var dy1 = cy1 - y00; - - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { - cx0 = cx1; - cy0 = cy1; - } - - return { - cx: cx0, - cy: cy0, - x0: -ox, - y0: -oy, - x1: cx0 * (radius / r - 1), - y1: cy0 * (radius / r - 1) - }; - } - - function normalizeCornerRadius(cr) { - var arr; - - if (isArray(cr)) { - var len = cr.length; - - if (!len) { - return cr; - } - - if (len === 1) { - arr = [cr[0], cr[0], 0, 0]; - } else if (len === 2) { - arr = [cr[0], cr[0], cr[1], cr[1]]; - } else if (len === 3) { - arr = cr.concat(cr[2]); - } else { - arr = cr; - } - } else { - arr = [cr, cr, cr, cr]; - } - - return arr; - } - - function buildPath$1(ctx, shape) { - var _a; - - var radius = mathMax$3(shape.r, 0); - var innerRadius = mathMax$3(shape.r0 || 0, 0); - var hasRadius = radius > 0; - var hasInnerRadius = innerRadius > 0; - - if (!hasRadius && !hasInnerRadius) { - return; - } - - if (!hasRadius) { - radius = innerRadius; - innerRadius = 0; - } - - if (innerRadius > radius) { - var tmp = radius; - radius = innerRadius; - innerRadius = tmp; - } - - var startAngle = shape.startAngle, - endAngle = shape.endAngle; - - if (isNaN(startAngle) || isNaN(endAngle)) { - return; - } - - var cx = shape.cx, - cy = shape.cy; - var clockwise = !!shape.clockwise; - var arc = mathAbs(endAngle - startAngle); - var mod = arc > PI2$3 && arc % PI2$3; - mod > e && (arc = mod); - - if (!(radius > e)) { - ctx.moveTo(cx, cy); - } else if (arc > PI2$3 - e) { - ctx.moveTo(cx + radius * mathCos$1(startAngle), cy + radius * mathSin$1(startAngle)); - ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); - - if (innerRadius > e) { - ctx.moveTo(cx + innerRadius * mathCos$1(endAngle), cy + innerRadius * mathSin$1(endAngle)); - ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); - } - } else { - var icrStart = void 0; - var icrEnd = void 0; - var ocrStart = void 0; - var ocrEnd = void 0; - var ocrs = void 0; - var ocre = void 0; - var icrs = void 0; - var icre = void 0; - var ocrMax = void 0; - var icrMax = void 0; - var limitedOcrMax = void 0; - var limitedIcrMax = void 0; - var xre = void 0; - var yre = void 0; - var xirs = void 0; - var yirs = void 0; - var xrs = radius * mathCos$1(startAngle); - var yrs = radius * mathSin$1(startAngle); - var xire = innerRadius * mathCos$1(endAngle); - var yire = innerRadius * mathSin$1(endAngle); - var hasArc = arc > e; - - if (hasArc) { - var cornerRadius = shape.cornerRadius; - - if (cornerRadius) { - _a = normalizeCornerRadius(cornerRadius), icrStart = _a[0], icrEnd = _a[1], ocrStart = _a[2], ocrEnd = _a[3]; - } - - var halfRd = mathAbs(radius - innerRadius) / 2; - ocrs = mathMin$3(halfRd, ocrStart); - ocre = mathMin$3(halfRd, ocrEnd); - icrs = mathMin$3(halfRd, icrStart); - icre = mathMin$3(halfRd, icrEnd); - limitedOcrMax = ocrMax = mathMax$3(ocrs, ocre); - limitedIcrMax = icrMax = mathMax$3(icrs, icre); - - if (ocrMax > e || icrMax > e) { - xre = radius * mathCos$1(endAngle); - yre = radius * mathSin$1(endAngle); - xirs = innerRadius * mathCos$1(startAngle); - yirs = innerRadius * mathSin$1(startAngle); - - if (arc < PI$3) { - var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire); - - if (it_1) { - var x0 = xrs - it_1[0]; - var y0 = yrs - it_1[1]; - var x1 = xre - it_1[0]; - var y1 = yre - it_1[1]; - var a = 1 / mathSin$1(mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2); - var b = mathSqrt(it_1[0] * it_1[0] + it_1[1] * it_1[1]); - limitedOcrMax = mathMin$3(ocrMax, (radius - b) / (a + 1)); - limitedIcrMax = mathMin$3(icrMax, (innerRadius - b) / (a - 1)); - } - } - } - } - - if (!hasArc) { - ctx.moveTo(cx + xrs, cy + yrs); - } else if (limitedOcrMax > e) { - var crStart = mathMin$3(ocrStart, limitedOcrMax); - var crEnd = mathMin$3(ocrEnd, limitedOcrMax); - var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, crStart, clockwise); - var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, crEnd, clockwise); - ctx.moveTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); - - if (limitedOcrMax < ocrMax && crStart === crEnd) { - ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedOcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); - } else { - crStart > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crStart, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); - ctx.arc(cx, cy, radius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), !clockwise); - crEnd > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crEnd, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); - } - } else { - ctx.moveTo(cx + xrs, cy + yrs); - ctx.arc(cx, cy, radius, startAngle, endAngle, !clockwise); - } - - if (!(innerRadius > e) || !hasArc) { - ctx.lineTo(cx + xire, cy + yire); - } else if (limitedIcrMax > e) { - var crStart = mathMin$3(icrStart, limitedIcrMax); - var crEnd = mathMin$3(icrEnd, limitedIcrMax); - var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -crEnd, clockwise); - var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -crStart, clockwise); - ctx.lineTo(cx + ct0.cx + ct0.x0, cy + ct0.cy + ct0.y0); - - if (limitedIcrMax < icrMax && crStart === crEnd) { - ctx.arc(cx + ct0.cx, cy + ct0.cy, limitedIcrMax, mathATan2(ct0.y0, ct0.x0), mathATan2(ct1.y0, ct1.x0), !clockwise); - } else { - crEnd > 0 && ctx.arc(cx + ct0.cx, cy + ct0.cy, crEnd, mathATan2(ct0.y0, ct0.x0), mathATan2(ct0.y1, ct0.x1), !clockwise); - ctx.arc(cx, cy, innerRadius, mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1), mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1), clockwise); - crStart > 0 && ctx.arc(cx + ct1.cx, cy + ct1.cy, crStart, mathATan2(ct1.y1, ct1.x1), mathATan2(ct1.y0, ct1.x0), !clockwise); - } - } else { - ctx.lineTo(cx + xire, cy + yire); - ctx.arc(cx, cy, innerRadius, endAngle, startAngle, clockwise); - } - } - - ctx.closePath(); - } - - var SectorShape = function () { - function SectorShape() { - this.cx = 0; - this.cy = 0; - this.r0 = 0; - this.r = 0; - this.startAngle = 0; - this.endAngle = Math.PI * 2; - this.clockwise = true; - this.cornerRadius = 0; - } - - return SectorShape; - }(); - - var Sector = function (_super) { - __extends(Sector, _super); - - function Sector(opts) { - return _super.call(this, opts) || this; - } - - Sector.prototype.getDefaultShape = function () { - return new SectorShape(); - }; - - Sector.prototype.buildPath = function (ctx, shape) { - buildPath$1(ctx, shape); - }; - - Sector.prototype.isZeroArea = function () { - return this.shape.startAngle === this.shape.endAngle || this.shape.r === this.shape.r0; - }; - - return Sector; - }(Path); - - Sector.prototype.type = 'sector'; - - var RingShape = function () { - function RingShape() { - this.cx = 0; - this.cy = 0; - this.r = 0; - this.r0 = 0; - } - - return RingShape; - }(); - - var Ring = function (_super) { - __extends(Ring, _super); - - function Ring(opts) { - return _super.call(this, opts) || this; - } - - Ring.prototype.getDefaultShape = function () { - return new RingShape(); - }; - - Ring.prototype.buildPath = function (ctx, shape) { - var x = shape.cx; - var y = shape.cy; - var PI2 = Math.PI * 2; - ctx.moveTo(x + shape.r, y); - ctx.arc(x, y, shape.r, 0, PI2, false); - ctx.moveTo(x + shape.r0, y); - ctx.arc(x, y, shape.r0, 0, PI2, true); - }; - - return Ring; - }(Path); - - Ring.prototype.type = 'ring'; - - function smoothBezier(points, smooth, isLoop, constraint) { - var cps = []; - var v = []; - var v1 = []; - var v2 = []; - var prevPoint; - var nextPoint; - var min; - var max; - - if (constraint) { - min = [Infinity, Infinity]; - max = [-Infinity, -Infinity]; - - for (var i = 0, len = points.length; i < len; i++) { - min$1(min, min, points[i]); - max$1(max, max, points[i]); - } - - min$1(min, min, constraint[0]); - max$1(max, max, constraint[1]); - } - - for (var i = 0, len = points.length; i < len; i++) { - var point = points[i]; - - if (isLoop) { - prevPoint = points[i ? i - 1 : len - 1]; - nextPoint = points[(i + 1) % len]; - } else { - if (i === 0 || i === len - 1) { - cps.push(clone$2(points[i])); - continue; - } else { - prevPoint = points[i - 1]; - nextPoint = points[i + 1]; - } - } - - sub(v, nextPoint, prevPoint); - scale$2(v, v, smooth); - var d0 = distance(point, prevPoint); - var d1 = distance(point, nextPoint); - var sum = d0 + d1; - - if (sum !== 0) { - d0 /= sum; - d1 /= sum; - } - - scale$2(v1, v, -d0); - scale$2(v2, v, d1); - var cp0 = add([], point, v1); - var cp1 = add([], point, v2); - - if (constraint) { - max$1(cp0, cp0, min); - min$1(cp0, cp0, max); - max$1(cp1, cp1, min); - min$1(cp1, cp1, max); - } - - cps.push(cp0); - cps.push(cp1); - } - - if (isLoop) { - cps.push(cps.shift()); - } - - return cps; - } - - function buildPath(ctx, shape, closePath) { - var smooth = shape.smooth; - var points = shape.points; - - if (points && points.length >= 2) { - if (smooth) { - var controlPoints = smoothBezier(points, smooth, closePath, shape.smoothConstraint); - ctx.moveTo(points[0][0], points[0][1]); - var len = points.length; - - for (var i = 0; i < (closePath ? len : len - 1); i++) { - var cp1 = controlPoints[i * 2]; - var cp2 = controlPoints[i * 2 + 1]; - var p = points[(i + 1) % len]; - ctx.bezierCurveTo(cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]); - } - } else { - ctx.moveTo(points[0][0], points[0][1]); - - for (var i = 1, l = points.length; i < l; i++) { - ctx.lineTo(points[i][0], points[i][1]); - } - } - - closePath && ctx.closePath(); - } - } - - var PolygonShape = function () { - function PolygonShape() { - this.points = null; - this.smooth = 0; - this.smoothConstraint = null; - } - - return PolygonShape; - }(); - - var Polygon = function (_super) { - __extends(Polygon, _super); - - function Polygon(opts) { - return _super.call(this, opts) || this; - } - - Polygon.prototype.getDefaultShape = function () { - return new PolygonShape(); - }; - - Polygon.prototype.buildPath = function (ctx, shape) { - buildPath(ctx, shape, true); - }; - - return Polygon; - }(Path); - - Polygon.prototype.type = 'polygon'; - - var PolylineShape = function () { - function PolylineShape() { - this.points = null; - this.percent = 1; - this.smooth = 0; - this.smoothConstraint = null; - } - - return PolylineShape; - }(); - - var Polyline = function (_super) { - __extends(Polyline, _super); - - function Polyline(opts) { - return _super.call(this, opts) || this; - } - - Polyline.prototype.getDefaultStyle = function () { - return { - stroke: '#000', - fill: null - }; - }; - - Polyline.prototype.getDefaultShape = function () { - return new PolylineShape(); - }; - - Polyline.prototype.buildPath = function (ctx, shape) { - buildPath(ctx, shape, false); - }; - - return Polyline; - }(Path); - - Polyline.prototype.type = 'polyline'; - var subPixelOptimizeOutputShape = {}; - - var LineShape = function () { - function LineShape() { - this.x1 = 0; - this.y1 = 0; - this.x2 = 0; - this.y2 = 0; - this.percent = 1; - } - - return LineShape; - }(); - - var Line = function (_super) { - __extends(Line, _super); - - function Line(opts) { - return _super.call(this, opts) || this; - } - - Line.prototype.getDefaultStyle = function () { - return { - stroke: '#000', - fill: null - }; - }; - - Line.prototype.getDefaultShape = function () { - return new LineShape(); - }; - - Line.prototype.buildPath = function (ctx, shape) { - var x1; - var y1; - var x2; - var y2; - - if (this.subPixelOptimize) { - var optimizedShape = subPixelOptimizeLine$1(subPixelOptimizeOutputShape, shape, this.style); - x1 = optimizedShape.x1; - y1 = optimizedShape.y1; - x2 = optimizedShape.x2; - y2 = optimizedShape.y2; - } else { - x1 = shape.x1; - y1 = shape.y1; - x2 = shape.x2; - y2 = shape.y2; - } - - var percent = shape.percent; - - if (percent === 0) { - return; - } - - ctx.moveTo(x1, y1); - - if (percent < 1) { - x2 = x1 * (1 - percent) + x2 * percent; - y2 = y1 * (1 - percent) + y2 * percent; - } - - ctx.lineTo(x2, y2); - }; - - Line.prototype.pointAt = function (p) { - var shape = this.shape; - return [shape.x1 * (1 - p) + shape.x2 * p, shape.y1 * (1 - p) + shape.y2 * p]; - }; - - return Line; - }(Path); - - Line.prototype.type = 'line'; - var out = []; - - var BezierCurveShape = function () { - function BezierCurveShape() { - this.x1 = 0; - this.y1 = 0; - this.x2 = 0; - this.y2 = 0; - this.cpx1 = 0; - this.cpy1 = 0; - this.percent = 1; - } - - return BezierCurveShape; - }(); - - function someVectorAt(shape, t, isTangent) { - var cpx2 = shape.cpx2; - var cpy2 = shape.cpy2; - - if (cpx2 != null || cpy2 != null) { - return [(isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)]; - } else { - return [(isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)]; - } - } - - var BezierCurve = function (_super) { - __extends(BezierCurve, _super); - - function BezierCurve(opts) { - return _super.call(this, opts) || this; - } - - BezierCurve.prototype.getDefaultStyle = function () { - return { - stroke: '#000', - fill: null - }; - }; - - BezierCurve.prototype.getDefaultShape = function () { - return new BezierCurveShape(); - }; - - BezierCurve.prototype.buildPath = function (ctx, shape) { - var x1 = shape.x1; - var y1 = shape.y1; - var x2 = shape.x2; - var y2 = shape.y2; - var cpx1 = shape.cpx1; - var cpy1 = shape.cpy1; - var cpx2 = shape.cpx2; - var cpy2 = shape.cpy2; - var percent = shape.percent; - - if (percent === 0) { - return; - } - - ctx.moveTo(x1, y1); - - if (cpx2 == null || cpy2 == null) { - if (percent < 1) { - quadraticSubdivide(x1, cpx1, x2, percent, out); - cpx1 = out[1]; - x2 = out[2]; - quadraticSubdivide(y1, cpy1, y2, percent, out); - cpy1 = out[1]; - y2 = out[2]; - } - - ctx.quadraticCurveTo(cpx1, cpy1, x2, y2); - } else { - if (percent < 1) { - cubicSubdivide(x1, cpx1, cpx2, x2, percent, out); - cpx1 = out[1]; - cpx2 = out[2]; - x2 = out[3]; - cubicSubdivide(y1, cpy1, cpy2, y2, percent, out); - cpy1 = out[1]; - cpy2 = out[2]; - y2 = out[3]; - } - - ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2); - } - }; - - BezierCurve.prototype.pointAt = function (t) { - return someVectorAt(this.shape, t, false); - }; - - BezierCurve.prototype.tangentAt = function (t) { - var p = someVectorAt(this.shape, t, true); - return normalize$1(p, p); - }; - - return BezierCurve; - }(Path); - - BezierCurve.prototype.type = 'bezier-curve'; - - var ArcShape = function () { - function ArcShape() { - this.cx = 0; - this.cy = 0; - this.r = 0; - this.startAngle = 0; - this.endAngle = Math.PI * 2; - this.clockwise = true; - } - - return ArcShape; - }(); - - var Arc = function (_super) { - __extends(Arc, _super); - - function Arc(opts) { - return _super.call(this, opts) || this; - } - - Arc.prototype.getDefaultStyle = function () { - return { - stroke: '#000', - fill: null - }; - }; - - Arc.prototype.getDefaultShape = function () { - return new ArcShape(); - }; - - Arc.prototype.buildPath = function (ctx, shape) { - var x = shape.cx; - var y = shape.cy; - var r = Math.max(shape.r, 0); - var startAngle = shape.startAngle; - var endAngle = shape.endAngle; - var clockwise = shape.clockwise; - var unitX = Math.cos(startAngle); - var unitY = Math.sin(startAngle); - ctx.moveTo(unitX * r + x, unitY * r + y); - ctx.arc(x, y, r, startAngle, endAngle, !clockwise); - }; - - return Arc; - }(Path); - - Arc.prototype.type = 'arc'; - - var CompoundPath = function (_super) { - __extends(CompoundPath, _super); - - function CompoundPath() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'compound'; - return _this; - } - - CompoundPath.prototype._updatePathDirty = function () { - var paths = this.shape.paths; - var dirtyPath = this.shapeChanged(); - - for (var i = 0; i < paths.length; i++) { - dirtyPath = dirtyPath || paths[i].shapeChanged(); - } - - if (dirtyPath) { - this.dirtyShape(); - } - }; - - CompoundPath.prototype.beforeBrush = function () { - this._updatePathDirty(); - - var paths = this.shape.paths || []; - var scale = this.getGlobalScale(); - - for (var i = 0; i < paths.length; i++) { - if (!paths[i].path) { - paths[i].createPathProxy(); - } - - paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold); - } - }; - - CompoundPath.prototype.buildPath = function (ctx, shape) { - var paths = shape.paths || []; - - for (var i = 0; i < paths.length; i++) { - paths[i].buildPath(ctx, paths[i].shape, true); - } - }; - - CompoundPath.prototype.afterBrush = function () { - var paths = this.shape.paths || []; - - for (var i = 0; i < paths.length; i++) { - paths[i].pathUpdated(); - } - }; - - CompoundPath.prototype.getBoundingRect = function () { - this._updatePathDirty.call(this); - - return Path.prototype.getBoundingRect.call(this); - }; - - return CompoundPath; - }(Path); - - var Gradient = function () { - function Gradient(colorStops) { - this.colorStops = colorStops || []; - } - - Gradient.prototype.addColorStop = function (offset, color) { - this.colorStops.push({ - offset: offset, - color: color - }); - }; - - return Gradient; - }(); - - var LinearGradient = function (_super) { - __extends(LinearGradient, _super); - - function LinearGradient(x, y, x2, y2, colorStops, globalCoord) { - var _this = _super.call(this, colorStops) || this; - - _this.x = x == null ? 0 : x; - _this.y = y == null ? 0 : y; - _this.x2 = x2 == null ? 1 : x2; - _this.y2 = y2 == null ? 0 : y2; - _this.type = 'linear'; - _this.global = globalCoord || false; - return _this; - } - - return LinearGradient; - }(Gradient); - - var RadialGradient = function (_super) { - __extends(RadialGradient, _super); - - function RadialGradient(x, y, r, colorStops, globalCoord) { - var _this = _super.call(this, colorStops) || this; - - _this.x = x == null ? 0.5 : x; - _this.y = y == null ? 0.5 : y; - _this.r = r == null ? 0.5 : r; - _this.type = 'radial'; - _this.global = globalCoord || false; - return _this; - } - - return RadialGradient; - }(Gradient); - - var extent = [0, 0]; - var extent2 = [0, 0]; - var minTv = new Point(); - var maxTv = new Point(); - - var OrientedBoundingRect = function () { - function OrientedBoundingRect(rect, transform) { - this._corners = []; - this._axes = []; - this._origin = [0, 0]; - - for (var i = 0; i < 4; i++) { - this._corners[i] = new Point(); - } - - for (var i = 0; i < 2; i++) { - this._axes[i] = new Point(); - } - - if (rect) { - this.fromBoundingRect(rect, transform); - } - } - - OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) { - var corners = this._corners; - var axes = this._axes; - var x = rect.x; - var y = rect.y; - var x2 = x + rect.width; - var y2 = y + rect.height; - corners[0].set(x, y); - corners[1].set(x2, y); - corners[2].set(x2, y2); - corners[3].set(x, y2); - - if (transform) { - for (var i = 0; i < 4; i++) { - corners[i].transform(transform); - } - } - - Point.sub(axes[0], corners[1], corners[0]); - Point.sub(axes[1], corners[3], corners[0]); - axes[0].normalize(); - axes[1].normalize(); - - for (var i = 0; i < 2; i++) { - this._origin[i] = axes[i].dot(corners[0]); - } - }; - - OrientedBoundingRect.prototype.intersect = function (other, mtv) { - var overlapped = true; - var noMtv = !mtv; - minTv.set(Infinity, Infinity); - maxTv.set(0, 0); - - if (!this._intersectCheckOneSide(this, other, minTv, maxTv, noMtv, 1)) { - overlapped = false; - - if (noMtv) { - return overlapped; - } - } - - if (!this._intersectCheckOneSide(other, this, minTv, maxTv, noMtv, -1)) { - overlapped = false; - - if (noMtv) { - return overlapped; - } - } - - if (!noMtv) { - Point.copy(mtv, overlapped ? minTv : maxTv); - } - - return overlapped; - }; - - OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) { - var overlapped = true; - - for (var i = 0; i < 2; i++) { - var axis = this._axes[i]; - - this._getProjMinMaxOnAxis(i, self._corners, extent); - - this._getProjMinMaxOnAxis(i, other._corners, extent2); - - if (extent[1] < extent2[0] || extent[0] > extent2[1]) { - overlapped = false; - - if (noMtv) { - return overlapped; - } - - var dist0 = Math.abs(extent2[0] - extent[1]); - var dist1 = Math.abs(extent[0] - extent2[1]); - - if (Math.min(dist0, dist1) > maxTv.len()) { - if (dist0 < dist1) { - Point.scale(maxTv, axis, -dist0 * inverse); - } else { - Point.scale(maxTv, axis, dist1 * inverse); - } - } - } else if (minTv) { - var dist0 = Math.abs(extent2[0] - extent[1]); - var dist1 = Math.abs(extent[0] - extent2[1]); - - if (Math.min(dist0, dist1) < minTv.len()) { - if (dist0 < dist1) { - Point.scale(minTv, axis, dist0 * inverse); - } else { - Point.scale(minTv, axis, -dist1 * inverse); - } - } - } - } - - return overlapped; - }; - - OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) { - var axis = this._axes[dim]; - var origin = this._origin; - var proj = corners[0].dot(axis) + origin[dim]; - var min = proj; - var max = proj; - - for (var i = 1; i < corners.length; i++) { - var proj_1 = corners[i].dot(axis) + origin[dim]; - min = Math.min(proj_1, min); - max = Math.max(proj_1, max); - } - - out[0] = min; - out[1] = max; - }; - - return OrientedBoundingRect; - }(); - - var m = []; - - var IncrementalDisplayable = function (_super) { - __extends(IncrementalDisplayable, _super); - - function IncrementalDisplayable() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.notClear = true; - _this.incremental = true; - _this._displayables = []; - _this._temporaryDisplayables = []; - _this._cursor = 0; - return _this; - } - - IncrementalDisplayable.prototype.traverse = function (cb, context) { - cb.call(context, this); - }; - - IncrementalDisplayable.prototype.useStyle = function () { - this.style = {}; - }; - - IncrementalDisplayable.prototype.getCursor = function () { - return this._cursor; - }; - - IncrementalDisplayable.prototype.innerAfterBrush = function () { - this._cursor = this._displayables.length; - }; - - IncrementalDisplayable.prototype.clearDisplaybles = function () { - this._displayables = []; - this._temporaryDisplayables = []; - this._cursor = 0; - this.markRedraw(); - this.notClear = false; - }; - - IncrementalDisplayable.prototype.clearTemporalDisplayables = function () { - this._temporaryDisplayables = []; - }; - - IncrementalDisplayable.prototype.addDisplayable = function (displayable, notPersistent) { - if (notPersistent) { - this._temporaryDisplayables.push(displayable); - } else { - this._displayables.push(displayable); - } - - this.markRedraw(); - }; - - IncrementalDisplayable.prototype.addDisplayables = function (displayables, notPersistent) { - notPersistent = notPersistent || false; - - for (var i = 0; i < displayables.length; i++) { - this.addDisplayable(displayables[i], notPersistent); - } - }; - - IncrementalDisplayable.prototype.getDisplayables = function () { - return this._displayables; - }; - - IncrementalDisplayable.prototype.getTemporalDisplayables = function () { - return this._temporaryDisplayables; - }; - - IncrementalDisplayable.prototype.eachPendingDisplayable = function (cb) { - for (var i = this._cursor; i < this._displayables.length; i++) { - cb && cb(this._displayables[i]); - } - - for (var i = 0; i < this._temporaryDisplayables.length; i++) { - cb && cb(this._temporaryDisplayables[i]); - } - }; - - IncrementalDisplayable.prototype.update = function () { - this.updateTransform(); - - for (var i = this._cursor; i < this._displayables.length; i++) { - var displayable = this._displayables[i]; - displayable.parent = this; - displayable.update(); - displayable.parent = null; - } - - for (var i = 0; i < this._temporaryDisplayables.length; i++) { - var displayable = this._temporaryDisplayables[i]; - displayable.parent = this; - displayable.update(); - displayable.parent = null; - } - }; - - IncrementalDisplayable.prototype.getBoundingRect = function () { - if (!this._rect) { - var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity); - - for (var i = 0; i < this._displayables.length; i++) { - var displayable = this._displayables[i]; - var childRect = displayable.getBoundingRect().clone(); - - if (displayable.needLocalTransform()) { - childRect.applyTransform(displayable.getLocalTransform(m)); - } - - rect.union(childRect); - } - - this._rect = rect; - } - - return this._rect; - }; - - IncrementalDisplayable.prototype.contain = function (x, y) { - var localPos = this.transformCoordToLocal(x, y); - var rect = this.getBoundingRect(); - - if (rect.contain(localPos[0], localPos[1])) { - for (var i = 0; i < this._displayables.length; i++) { - var displayable = this._displayables[i]; - - if (displayable.contain(x, y)) { - return true; - } - } - } - - return false; - }; - - return IncrementalDisplayable; - }(Displayable); // Stored properties for further transition. - - - var transitionStore = makeInner(); - /** - * Return null if animation is disabled. - */ - - function getAnimationConfig(animationType, animatableModel, dataIndex, // Extra opts can override the option in animatable model. - extraOpts, // TODO It's only for pictorial bar now. - extraDelayParams) { - var animationPayload; // Check if there is global animation configuration from dataZoom/resize can override the config in option. - // If animation is enabled. Will use this animation config in payload. - // If animation is disabled. Just ignore it. - - if (animatableModel && animatableModel.ecModel) { - var updatePayload = animatableModel.ecModel.getUpdatePayload(); - animationPayload = updatePayload && updatePayload.animation; - } - - var animationEnabled = animatableModel && animatableModel.isAnimationEnabled(); - var isUpdate = animationType === 'update'; - - if (animationEnabled) { - var duration = void 0; - var easing = void 0; - var delay = void 0; - - if (extraOpts) { - duration = retrieve2(extraOpts.duration, 200); - easing = retrieve2(extraOpts.easing, 'cubicOut'); - delay = 0; - } else { - duration = animatableModel.getShallow(isUpdate ? 'animationDurationUpdate' : 'animationDuration'); - easing = animatableModel.getShallow(isUpdate ? 'animationEasingUpdate' : 'animationEasing'); - delay = animatableModel.getShallow(isUpdate ? 'animationDelayUpdate' : 'animationDelay'); - } // animation from payload has highest priority. - - - if (animationPayload) { - animationPayload.duration != null && (duration = animationPayload.duration); - animationPayload.easing != null && (easing = animationPayload.easing); - animationPayload.delay != null && (delay = animationPayload.delay); - } - - if (isFunction(delay)) { - delay = delay(dataIndex, extraDelayParams); - } - - if (isFunction(duration)) { - duration = duration(dataIndex); - } - - var config = { - duration: duration || 0, - delay: delay, - easing: easing - }; - return config; - } else { - return null; - } - } - - function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) { - var isFrom = false; - var removeOpt; - - if (isFunction(dataIndex)) { - during = cb; - cb = dataIndex; - dataIndex = null; - } else if (isObject$2(dataIndex)) { - cb = dataIndex.cb; - during = dataIndex.during; - isFrom = dataIndex.isFrom; - removeOpt = dataIndex.removeOpt; - dataIndex = dataIndex.dataIndex; - } - - var isRemove = animationType === 'leave'; - - if (!isRemove) { - // Must stop the remove animation. - el.stopAnimation('leave'); - } - - var animationConfig = getAnimationConfig(animationType, animatableModel, dataIndex, isRemove ? removeOpt || {} : null, animatableModel && animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null); - - if (animationConfig && animationConfig.duration > 0) { - var duration = animationConfig.duration; - var animationDelay = animationConfig.delay; - var animationEasing = animationConfig.easing; - var animateConfig = { - duration: duration, - delay: animationDelay || 0, - easing: animationEasing, - done: cb, - force: !!cb || !!during, - // Set to final state in update/init animation. - // So the post processing based on the path shape can be done correctly. - setToFinal: !isRemove, - scope: animationType, - during: during - }; - isFrom ? el.animateFrom(props, animateConfig) : el.animateTo(props, animateConfig); - } else { - el.stopAnimation(); // If `isFrom`, the props is the "from" props. - - !isFrom && el.attr(props); // Call during at least once. - - during && during(1); - cb && cb(); - } - } - /** - * Update graphic element properties with or without animation according to the - * configuration in series. - * - * Caution: this method will stop previous animation. - * So do not use this method to one element twice before - * animation starts, unless you know what you are doing. - * @example - * graphic.updateProps(el, { - * position: [100, 100] - * }, seriesModel, dataIndex, function () { console.log('Animation done!'); }); - * // Or - * graphic.updateProps(el, { - * position: [100, 100] - * }, seriesModel, function () { console.log('Animation done!'); }); - */ - - - function updateProps$1(el, props, // TODO: TYPE AnimatableModel - animatableModel, dataIndex, cb, during) { - animateOrSetProps('update', el, props, animatableModel, dataIndex, cb, during); - } - /** - * Init graphic element properties with or without animation according to the - * configuration in series. - * - * Caution: this method will stop previous animation. - * So do not use this method to one element twice before - * animation starts, unless you know what you are doing. - */ - - - function initProps(el, props, animatableModel, dataIndex, cb, during) { - animateOrSetProps('enter', el, props, animatableModel, dataIndex, cb, during); - } - /** - * If element is removed. - * It can determine if element is having remove animation. - */ - - - function isElementRemoved(el) { - if (!el.__zr) { - return true; - } - - for (var i = 0; i < el.animators.length; i++) { - var animator = el.animators[i]; - - if (animator.scope === 'leave') { - return true; - } - } - - return false; - } - /** - * Remove graphic element - */ - - - function removeElement(el, props, animatableModel, dataIndex, cb, during) { - // Don't do remove animation twice. - if (isElementRemoved(el)) { - return; - } - - animateOrSetProps('leave', el, props, animatableModel, dataIndex, cb, during); - } - - function fadeOutDisplayable(el, animatableModel, dataIndex, done) { - el.removeTextContent(); - el.removeTextGuideLine(); - removeElement(el, { - style: { - opacity: 0 - } - }, animatableModel, dataIndex, done); - } - - function removeElementWithFadeOut(el, animatableModel, dataIndex) { - function doRemove() { - el.parent && el.parent.remove(el); - } // Hide label and labelLine first - // TODO Also use fade out animation? - - - if (!el.isGroup) { - fadeOutDisplayable(el, animatableModel, dataIndex, doRemove); - } else { - el.traverse(function (disp) { - if (!disp.isGroup) { - // Can invoke doRemove multiple times. - fadeOutDisplayable(disp, animatableModel, dataIndex, doRemove); - } - }); - } - } - /** - * Save old style for style transition in universalTransition module. - * It's used when element will be reused in each render. - * For chart like map, heatmap, which will always create new element. - * We don't need to save this because universalTransition can get old style from the old element - */ - - - function saveOldStyle(el) { - transitionStore(el).oldStyle = el.style; - } - - var mathMax$2 = Math.max; - var mathMin$2 = Math.min; - var _customShapeMap = {}; - /** - * Extend shape with parameters - */ - - function extendShape(opts) { - return Path.extend(opts); - } - - var extendPathFromString = extendFromString; - /** - * Extend path - */ - - function extendPath(pathData, opts) { - return extendPathFromString(pathData, opts); - } - /** - * Register a user defined shape. - * The shape class can be fetched by `getShapeClass` - * This method will overwrite the registered shapes, including - * the registered built-in shapes, if using the same `name`. - * The shape can be used in `custom series` and - * `graphic component` by declaring `{type: name}`. - * - * @param name - * @param ShapeClass Can be generated by `extendShape`. - */ - - - function registerShape(name, ShapeClass) { - _customShapeMap[name] = ShapeClass; - } - /** - * Find shape class registered by `registerShape`. Usually used in - * fetching user defined shape. - * - * [Caution]: - * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared - * to use user registered shapes. - * Because the built-in shape (see `getBuiltInShape`) will be registered by - * `registerShape` by default. That enables users to get both built-in - * shapes as well as the shapes belonging to themsleves. But users can overwrite - * the built-in shapes by using names like 'circle', 'rect' via calling - * `registerShape`. So the echarts inner featrues should not fetch shapes from here - * in case that it is overwritten by users, except that some features, like - * `custom series`, `graphic component`, do it deliberately. - * - * (2) In the features like `custom series`, `graphic component`, the user input - * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic - * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names - * are reserved names, that is, if some user registers a shape named `'image'`, - * the shape will not be used. If we intending to add some more reserved names - * in feature, that might bring break changes (disable some existing user shape - * names). But that case probably rarely happens. So we don't make more mechanism - * to resolve this issue here. - * - * @param name - * @return The shape class. If not found, return nothing. - */ - - - function getShapeClass(name) { - if (_customShapeMap.hasOwnProperty(name)) { - return _customShapeMap[name]; - } - } - /** - * Create a path element from path data string - * @param pathData - * @param opts - * @param rect - * @param layout 'center' or 'cover' default to be cover - */ - - - function makePath(pathData, opts, rect, layout) { - var path = createFromString(pathData, opts); - - if (rect) { - if (layout === 'center') { - rect = centerGraphic(rect, path.getBoundingRect()); - } - - resizePath(path, rect); - } - - return path; - } - /** - * Create a image element from image url - * @param imageUrl image url - * @param opts options - * @param rect constrain rect - * @param layout 'center' or 'cover'. Default to be 'cover' - */ - - - function makeImage(imageUrl, rect, layout) { - var zrImg = new ZRImage({ - style: { - image: imageUrl, - x: rect.x, - y: rect.y, - width: rect.width, - height: rect.height - }, - onload: function (img) { - if (layout === 'center') { - var boundingRect = { - width: img.width, - height: img.height - }; - zrImg.setStyle(centerGraphic(rect, boundingRect)); - } - } - }); - return zrImg; - } - /** - * Get position of centered element in bounding box. - * - * @param rect element local bounding box - * @param boundingRect constraint bounding box - * @return element position containing x, y, width, and height - */ - - - function centerGraphic(rect, boundingRect) { - // Set rect to center, keep width / height ratio. - var aspect = boundingRect.width / boundingRect.height; - var width = rect.height * aspect; - var height; - - if (width <= rect.width) { - height = rect.height; - } else { - width = rect.width; - height = width / aspect; - } - - var cx = rect.x + rect.width / 2; - var cy = rect.y + rect.height / 2; - return { - x: cx - width / 2, - y: cy - height / 2, - width: width, - height: height - }; - } - - var mergePath = mergePath$1; - /** - * Resize a path to fit the rect - * @param path - * @param rect - */ - - function resizePath(path, rect) { - if (!path.applyTransform) { - return; - } - - var pathRect = path.getBoundingRect(); - var m = pathRect.calculateTransform(rect); - path.applyTransform(m); - } - /** - * Sub pixel optimize line for canvas - */ - - - function subPixelOptimizeLine(shape, lineWidth) { - subPixelOptimizeLine$1(shape, shape, { - lineWidth: lineWidth - }); - return shape; - } - /** - * Sub pixel optimize rect for canvas - */ - - - function subPixelOptimizeRect(param) { - subPixelOptimizeRect$1(param.shape, param.shape, param.style); - return param; - } - /** - * Sub pixel optimize for canvas - * - * @param position Coordinate, such as x, y - * @param lineWidth Should be nonnegative integer. - * @param positiveOrNegative Default false (negative). - * @return Optimized position. - */ - - - var subPixelOptimize = subPixelOptimize$1; - /** - * Get transform matrix of target (param target), - * in coordinate of its ancestor (param ancestor) - * - * @param target - * @param [ancestor] - */ - - function getTransform(target, ancestor) { - var mat = identity([]); - - while (target && target !== ancestor) { - mul(mat, target.getLocalTransform(), mat); - target = target.parent; - } - - return mat; - } - /** - * Apply transform to an vertex. - * @param target [x, y] - * @param transform Can be: - * + Transform matrix: like [1, 0, 0, 1, 0, 0] - * + {position, rotation, scale}, the same as `zrender/Transformable`. - * @param invert Whether use invert matrix. - * @return [x, y] - */ - - - function applyTransform(target, transform, invert$1) { - if (transform && !isArrayLike(transform)) { - transform = Transformable.getLocalTransform(transform); - } - - if (invert$1) { - transform = invert([], transform); - } - - return applyTransform$1([], target, transform); - } - /** - * @param direction 'left' 'right' 'top' 'bottom' - * @param transform Transform matrix: like [1, 0, 0, 1, 0, 0] - * @param invert Whether use invert matrix. - * @return Transformed direction. 'left' 'right' 'top' 'bottom' - */ - - - function transformDirection(direction, transform, invert) { - // Pick a base, ensure that transform result will not be (0, 0). - var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]); - var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]); - var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0]; - vertex = applyTransform(vertex, transform, invert); - return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top'; - } - - function isNotGroup(el) { - return !el.isGroup; - } - - function isPath(el) { - return el.shape != null; - } - /** - * Apply group transition animation from g1 to g2. - * If no animatableModel, no animation. - */ - - - function groupTransition(g1, g2, animatableModel) { - if (!g1 || !g2) { - return; - } - - function getElMap(g) { - var elMap = {}; - g.traverse(function (el) { - if (isNotGroup(el) && el.anid) { - elMap[el.anid] = el; - } - }); - return elMap; - } - - function getAnimatableProps(el) { - var obj = { - x: el.x, - y: el.y, - rotation: el.rotation - }; - - if (isPath(el)) { - obj.shape = extend({}, el.shape); - } - - return obj; - } - - var elMap1 = getElMap(g1); - g2.traverse(function (el) { - if (isNotGroup(el) && el.anid) { - var oldEl = elMap1[el.anid]; - - if (oldEl) { - var newProp = getAnimatableProps(el); - el.attr(getAnimatableProps(oldEl)); - updateProps$1(el, newProp, animatableModel, getECData(el).dataIndex); - } - } - }); - } - - function clipPointsByRect(points, rect) { - // FIXME: This way might be incorrect when graphic clipped by a corner - // and when element has a border. - return map$1(points, function (point) { - var x = point[0]; - x = mathMax$2(x, rect.x); - x = mathMin$2(x, rect.x + rect.width); - var y = point[1]; - y = mathMax$2(y, rect.y); - y = mathMin$2(y, rect.y + rect.height); - return [x, y]; - }); - } - /** - * Return a new clipped rect. If rect size are negative, return undefined. - */ - - - function clipRectByRect(targetRect, rect) { - var x = mathMax$2(targetRect.x, rect.x); - var x2 = mathMin$2(targetRect.x + targetRect.width, rect.x + rect.width); - var y = mathMax$2(targetRect.y, rect.y); - var y2 = mathMin$2(targetRect.y + targetRect.height, rect.y + rect.height); // If the total rect is cliped, nothing, including the border, - // should be painted. So return undefined. - - if (x2 >= x && y2 >= y) { - return { - x: x, - y: y, - width: x2 - x, - height: y2 - y - }; - } - } - - function createIcon(iconStr, // Support 'image://' or 'path://' or direct svg path. - opt, rect) { - var innerOpts = extend({ - rectHover: true - }, opt); - var style = innerOpts.style = { - strokeNoScale: true - }; - rect = rect || { - x: -1, - y: -1, - width: 2, - height: 2 - }; - - if (iconStr) { - return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), defaults(style, rect), new ZRImage(innerOpts)) : makePath(iconStr.replace('path://', ''), innerOpts, rect, 'center'); - } - } - /** - * Return `true` if the given line (line `a`) and the given polygon - * are intersect. - * Note that we do not count colinear as intersect here because no - * requirement for that. We could do that if required in future. - */ - - - function linePolygonIntersect(a1x, a1y, a2x, a2y, points) { - for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) { - var p = points[i]; - - if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) { - return true; - } - - p2 = p; - } - } - /** - * Return `true` if the given two lines (line `a` and line `b`) - * are intersect. - * Note that we do not count colinear as intersect here because no - * requirement for that. We could do that if required in future. - */ - - - function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { - // let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`. - var mx = a2x - a1x; - var my = a2y - a1y; - var nx = b2x - b1x; - var ny = b2y - b1y; // `vec_m` and `vec_n` are parallel iff - // existing `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`. - - var nmCrossProduct = crossProduct2d(nx, ny, mx, my); - - if (nearZero(nmCrossProduct)) { - return false; - } // `vec_m` and `vec_n` are intersect iff - // existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`, - // such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)` - // and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`. - - - var b1a1x = a1x - b1x; - var b1a1y = a1y - b1y; - var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct; - - if (q < 0 || q > 1) { - return false; - } - - var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct; - - if (p < 0 || p > 1) { - return false; - } - - return true; - } - /** - * Cross product of 2-dimension vector. - */ - - - function crossProduct2d(x1, y1, x2, y2) { - return x1 * y2 - x2 * y1; - } - - function nearZero(val) { - return val <= 1e-6 && val >= -1e-6; - } - - function setTooltipConfig(opt) { - var itemTooltipOption = opt.itemTooltipOption; - var componentModel = opt.componentModel; - var itemName = opt.itemName; - var itemTooltipOptionObj = isString(itemTooltipOption) ? { - formatter: itemTooltipOption - } : itemTooltipOption; - var mainType = componentModel.mainType; - var componentIndex = componentModel.componentIndex; - var formatterParams = { - componentType: mainType, - name: itemName, - $vars: ['name'] - }; - formatterParams[mainType + 'Index'] = componentIndex; - var formatterParamsExtra = opt.formatterParamsExtra; - - if (formatterParamsExtra) { - each$4(keys(formatterParamsExtra), function (key) { - if (!hasOwn(formatterParams, key)) { - formatterParams[key] = formatterParamsExtra[key]; - formatterParams.$vars.push(key); - } - }); - } - - var ecData = getECData(opt.el); - ecData.componentMainType = mainType; - ecData.componentIndex = componentIndex; - ecData.tooltipConfig = { - name: itemName, - option: defaults({ - content: itemName, - formatterParams: formatterParams - }, itemTooltipOptionObj) - }; - } - - function traverseElement(el, cb) { - var stopped; // TODO - // Polyfill for fixing zrender group traverse don't visit it's root issue. - - if (el.isGroup) { - stopped = cb(el); - } - - if (!stopped) { - el.traverse(cb); - } - } - - function traverseElements(els, cb) { - if (els) { - if (isArray(els)) { - for (var i = 0; i < els.length; i++) { - traverseElement(els[i], cb); - } - } else { - traverseElement(els, cb); - } - } - } // Register built-in shapes. These shapes might be overwritten - // by users, although we do not recommend that. - - - registerShape('circle', Circle); - registerShape('ellipse', Ellipse); - registerShape('sector', Sector); - registerShape('ring', Ring); - registerShape('polygon', Polygon); - registerShape('polyline', Polyline); - registerShape('rect', Rect); - registerShape('line', Line); - registerShape('bezierCurve', BezierCurve); - registerShape('arc', Arc); - var graphic$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - Arc: Arc, - BezierCurve: BezierCurve, - BoundingRect: BoundingRect, - Circle: Circle, - CompoundPath: CompoundPath, - Ellipse: Ellipse, - Group: Group$2, - Image: ZRImage, - IncrementalDisplayable: IncrementalDisplayable, - Line: Line, - LinearGradient: LinearGradient, - OrientedBoundingRect: OrientedBoundingRect, - Path: Path, - Point: Point, - Polygon: Polygon, - Polyline: Polyline, - RadialGradient: RadialGradient, - Rect: Rect, - Ring: Ring, - Sector: Sector, - Text: ZRText, - applyTransform: applyTransform, - clipPointsByRect: clipPointsByRect, - clipRectByRect: clipRectByRect, - createIcon: createIcon, - extendPath: extendPath, - extendShape: extendShape, - getShapeClass: getShapeClass, - getTransform: getTransform, - groupTransition: groupTransition, - initProps: initProps, - isElementRemoved: isElementRemoved, - lineLineIntersect: lineLineIntersect, - linePolygonIntersect: linePolygonIntersect, - makeImage: makeImage, - makePath: makePath, - mergePath: mergePath, - registerShape: registerShape, - removeElement: removeElement, - removeElementWithFadeOut: removeElementWithFadeOut, - resizePath: resizePath, - setTooltipConfig: setTooltipConfig, - subPixelOptimize: subPixelOptimize, - subPixelOptimizeLine: subPixelOptimizeLine, - subPixelOptimizeRect: subPixelOptimizeRect, - transformDirection: transformDirection, - traverseElements: traverseElements, - updateProps: updateProps$1 - }); - var EMPTY_OBJ = {}; - - function setLabelText(label, labelTexts) { - for (var i = 0; i < SPECIAL_STATES.length; i++) { - var stateName = SPECIAL_STATES[i]; - var text = labelTexts[stateName]; - var state = label.ensureState(stateName); - state.style = state.style || {}; - state.style.text = text; - } - - var oldStates = label.currentStates.slice(); - label.clearStates(true); - label.setStyle({ - text: labelTexts.normal - }); - label.useStates(oldStates, true); - } - - function getLabelText(opt, stateModels, interpolatedValue) { - var labelFetcher = opt.labelFetcher; - var labelDataIndex = opt.labelDataIndex; - var labelDimIndex = opt.labelDimIndex; - var normalModel = stateModels.normal; - var baseText; - - if (labelFetcher) { - baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), interpolatedValue != null ? { - interpolatedValue: interpolatedValue - } : null); - } - - if (baseText == null) { - baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, interpolatedValue) : opt.defaultText; - } - - var statesText = { - normal: baseText - }; - - for (var i = 0; i < SPECIAL_STATES.length; i++) { - var stateName = SPECIAL_STATES[i]; - var stateModel = stateModels[stateName]; - statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText); - } - - return statesText; - } - - function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified // TODO specified position? - ) { - opt = opt || EMPTY_OBJ; - var isSetOnText = targetEl instanceof ZRText; - var needsCreateText = false; - - for (var i = 0; i < DISPLAY_STATES.length; i++) { - var stateModel = labelStatesModels[DISPLAY_STATES[i]]; - - if (stateModel && stateModel.getShallow('show')) { - needsCreateText = true; - break; - } - } - - var textContent = isSetOnText ? targetEl : targetEl.getTextContent(); - - if (needsCreateText) { - if (!isSetOnText) { - // Reuse the previous - if (!textContent) { - textContent = new ZRText(); - targetEl.setTextContent(textContent); - } // Use same state proxy - - - if (targetEl.stateProxy) { - textContent.stateProxy = targetEl.stateProxy; - } - } - - var labelStatesTexts = getLabelText(opt, labelStatesModels); - var normalModel = labelStatesModels.normal; - var showNormal = !!normalModel.getShallow('show'); - var normalStyle = createTextStyle$1(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText); - normalStyle.text = labelStatesTexts.normal; - - if (!isSetOnText) { - // Always create new - targetEl.setTextConfig(createTextConfig(normalModel, opt, false)); - } - - for (var i = 0; i < SPECIAL_STATES.length; i++) { - var stateName = SPECIAL_STATES[i]; - var stateModel = labelStatesModels[stateName]; - - if (stateModel) { - var stateObj = textContent.ensureState(stateName); - var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal); - - if (stateShow !== showNormal) { - stateObj.ignore = !stateShow; - } - - stateObj.style = createTextStyle$1(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText); - stateObj.style.text = labelStatesTexts[stateName]; - - if (!isSetOnText) { - var targetElEmphasisState = targetEl.ensureState(stateName); - targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true); - } - } - } // PENDING: if there is many requirements that emphasis position - // need to be different from normal position, we might consider - // auto silent is those cases. - - - textContent.silent = !!normalModel.getShallow('silent'); // Keep x and y - - if (textContent.style.x != null) { - normalStyle.x = textContent.style.x; - } - - if (textContent.style.y != null) { - normalStyle.y = textContent.style.y; - } - - textContent.ignore = !showNormal; // Always create new style. - - textContent.useStyle(normalStyle); - textContent.dirty(); - - if (opt.enableTextSetter) { - labelInner(textContent).setLabelText = function (interpolatedValue) { - var labelStatesTexts = getLabelText(opt, labelStatesModels, interpolatedValue); - setLabelText(textContent, labelStatesTexts); - }; - } - } else if (textContent) { - // Not display rich text. - textContent.ignore = true; - } - - targetEl.dirty(); - } - - function getLabelStatesModels(itemModel, labelName) { - labelName = labelName || 'label'; - var statesModels = { - normal: itemModel.getModel(labelName) - }; - - for (var i = 0; i < SPECIAL_STATES.length; i++) { - var stateName = SPECIAL_STATES[i]; - statesModels[stateName] = itemModel.getModel([stateName, labelName]); - } - - return statesModels; - } - /** - * Set basic textStyle properties. - */ - - - function createTextStyle$1(textStyleModel, specifiedTextStyle, // Fixed style in the code. Can't be set by model. - opt, isNotNormal, isAttached // If text is attached on an element. If so, auto color will handling in zrender. - ) { - var textStyle = {}; - setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached); - specifiedTextStyle && extend(textStyle, specifiedTextStyle); // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false); - - return textStyle; - } - - function createTextConfig(textStyleModel, opt, isNotNormal) { - opt = opt || {}; - var textConfig = {}; - var labelPosition; - var labelRotate = textStyleModel.getShallow('rotate'); - var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5); - var labelOffset = textStyleModel.getShallow('offset'); - labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside'); // 'outside' is not a valid zr textPostion value, but used - // in bar series, and magric type should be considered. - - labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top'); - - if (labelPosition != null) { - textConfig.position = labelPosition; - } - - if (labelOffset != null) { - textConfig.offset = labelOffset; - } - - if (labelRotate != null) { - labelRotate *= Math.PI / 180; - textConfig.rotation = labelRotate; - } - - if (labelDistance != null) { - textConfig.distance = labelDistance; - } // fill and auto is determined by the color of path fill if it's not specified by developers. - - - textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto'; - return textConfig; - } - /** - * The uniform entry of set text style, that is, retrieve style definitions - * from `model` and set to `textStyle` object. - * - * Never in merge mode, but in overwrite mode, that is, all of the text style - * properties will be set. (Consider the states of normal and emphasis and - * default value can be adopted, merge would make the logic too complicated - * to manage.) - */ - - - function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) { - // Consider there will be abnormal when merge hover style to normal style if given default value. - opt = opt || EMPTY_OBJ; - var ecModel = textStyleModel.ecModel; - var globalTextStyle = ecModel && ecModel.option.textStyle; // Consider case: - // { - // data: [{ - // value: 12, - // label: { - // rich: { - // // no 'a' here but using parent 'a'. - // } - // } - // }], - // rich: { - // a: { ... } - // } - // } - - var richItemNames = getRichItemNames(textStyleModel); - var richResult; - - if (richItemNames) { - richResult = {}; - - for (var name_1 in richItemNames) { - if (richItemNames.hasOwnProperty(name_1)) { - // Cascade is supported in rich. - var richTextStyle = textStyleModel.getModel(['rich', name_1]); // In rich, never `disableBox`. - // FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`, - // the default color `'blue'` will not be adopted if no color declared in `rich`. - // That might confuses users. So probably we should put `textStyleModel` as the - // root ancestor of the `richTextStyle`. But that would be a break change. - - setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true); - } - } - } - - if (richResult) { - textStyle.rich = richResult; - } - - var overflow = textStyleModel.get('overflow'); - - if (overflow) { - textStyle.overflow = overflow; - } - - var margin = textStyleModel.get('minMargin'); - - if (margin != null) { - textStyle.margin = margin; - } - - setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false); - } // Consider case: - // { - // data: [{ - // value: 12, - // label: { - // rich: { - // // no 'a' here but using parent 'a'. - // } - // } - // }], - // rich: { - // a: { ... } - // } - // } - // TODO TextStyleModel - - - function getRichItemNames(textStyleModel) { - // Use object to remove duplicated names. - var richItemNameMap; - - while (textStyleModel && textStyleModel !== textStyleModel.ecModel) { - var rich = (textStyleModel.option || EMPTY_OBJ).rich; - - if (rich) { - richItemNameMap = richItemNameMap || {}; - var richKeys = keys(rich); - - for (var i = 0; i < richKeys.length; i++) { - var richKey = richKeys[i]; - richItemNameMap[richKey] = 1; - } - } - - textStyleModel = textStyleModel.parentModel; - } - - return richItemNameMap; - } - - var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY']; - var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign', 'ellipsis']; - var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; - - function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) { - // In merge mode, default value should not be given. - globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ; - var inheritColor = opt && opt.inheritColor; - var fillColor = textStyleModel.getShallow('color'); - var strokeColor = textStyleModel.getShallow('textBorderColor'); - var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity); - - if (fillColor === 'inherit' || fillColor === 'auto') { - { - if (fillColor === 'auto') { - deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); - } - } - - if (inheritColor) { - fillColor = inheritColor; - } else { - fillColor = null; - } - } - - if (strokeColor === 'inherit' || strokeColor === 'auto') { - { - if (strokeColor === 'auto') { - deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); - } - } - - if (inheritColor) { - strokeColor = inheritColor; - } else { - strokeColor = null; - } - } - - if (!isAttached) { - // Only use default global textStyle.color if text is individual. - // Otherwise it will use the strategy of attached text color because text may be on a path. - fillColor = fillColor || globalTextStyle.color; - strokeColor = strokeColor || globalTextStyle.textBorderColor; - } - - if (fillColor != null) { - textStyle.fill = fillColor; - } - - if (strokeColor != null) { - textStyle.stroke = strokeColor; - } - - var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth); - - if (textBorderWidth != null) { - textStyle.lineWidth = textBorderWidth; - } - - var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType); - - if (textBorderType != null) { - textStyle.lineDash = textBorderType; - } - - var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset); - - if (textBorderDashOffset != null) { - textStyle.lineDashOffset = textBorderDashOffset; - } - - if (!isNotNormal && opacity == null && !inRich) { - opacity = opt && opt.defaultOpacity; - } - - if (opacity != null) { - textStyle.opacity = opacity; - } // TODO - - - if (!isNotNormal && !isAttached) { - // Set default finally. - if (textStyle.fill == null && opt.inheritColor) { - textStyle.fill = opt.inheritColor; - } - } // Do not use `getFont` here, because merge should be supported, where - // part of these properties may be changed in emphasis style, and the - // others should remain their original value got from normal style. - - - for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) { - var key = TEXT_PROPS_WITH_GLOBAL[i]; - var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]); - - if (val != null) { - textStyle[key] = val; - } - } - - for (var i = 0; i < TEXT_PROPS_SELF.length; i++) { - var key = TEXT_PROPS_SELF[i]; - var val = textStyleModel.getShallow(key); - - if (val != null) { - textStyle[key] = val; - } - } - - if (textStyle.verticalAlign == null) { - var baseline = textStyleModel.getShallow('baseline'); - - if (baseline != null) { - textStyle.verticalAlign = baseline; - } - } - - if (!isBlock || !opt.disableBox) { - for (var i = 0; i < TEXT_PROPS_BOX.length; i++) { - var key = TEXT_PROPS_BOX[i]; - var val = textStyleModel.getShallow(key); - - if (val != null) { - textStyle[key] = val; - } - } - - var borderType = textStyleModel.getShallow('borderType'); - - if (borderType != null) { - textStyle.borderDash = borderType; - } - - if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) { - { - if (textStyle.backgroundColor === 'auto') { - deprecateReplaceLog('backgroundColor: \'auto\'', 'backgroundColor: \'inherit\''); - } - } - textStyle.backgroundColor = inheritColor; - } - - if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) { - { - if (textStyle.borderColor === 'auto') { - deprecateReplaceLog('borderColor: \'auto\'', 'borderColor: \'inherit\''); - } - } - textStyle.borderColor = inheritColor; - } - } - } - - function getFont(opt, ecModel) { - var gTextStyleModel = ecModel && ecModel.getModel('textStyle'); - return trim([// FIXME in node-canvas fontWeight is before fontStyle - opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' ')); - } - - var labelInner = makeInner(); - - function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) { - if (!label) { - return; - } - - var obj = labelInner(label); - obj.prevValue = obj.value; - obj.value = value; - var normalLabelModel = labelStatesModels.normal; - obj.valueAnimation = normalLabelModel.get('valueAnimation'); - - if (obj.valueAnimation) { - obj.precision = normalLabelModel.get('precision'); - obj.defaultInterpolatedText = getDefaultText; - obj.statesModels = labelStatesModels; - } - } - - function animateLabelValue(textEl, dataIndex, data, animatableModel, labelFetcher) { - var labelInnerStore = labelInner(textEl); - - if (!labelInnerStore.valueAnimation || labelInnerStore.prevValue === labelInnerStore.value) { - // Value not changed, no new label animation - return; - } - - var defaultInterpolatedText = labelInnerStore.defaultInterpolatedText; // Consider the case that being animating, do not use the `obj.value`, - // Otherwise it will jump to the `obj.value` when this new animation started. - - var currValue = retrieve2(labelInnerStore.interpolatedValue, labelInnerStore.prevValue); - var targetValue = labelInnerStore.value; - - function during(percent) { - var interpolated = interpolateRawValues(data, labelInnerStore.precision, currValue, targetValue, percent); - labelInnerStore.interpolatedValue = percent === 1 ? null : interpolated; - var labelText = getLabelText({ - labelDataIndex: dataIndex, - labelFetcher: labelFetcher, - defaultText: defaultInterpolatedText ? defaultInterpolatedText(interpolated) : interpolated + '' - }, labelInnerStore.statesModels, interpolated); - setLabelText(textEl, labelText); - } - - textEl.percent = 0; - (labelInnerStore.prevValue == null ? initProps : updateProps$1)(textEl, { - // percent is used to prevent animation from being aborted #15916 - percent: 1 - }, animatableModel, dataIndex, null, during); - } - - var PATH_COLOR = ['textStyle', 'color']; - var textStyleParams = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'padding', 'lineHeight', 'rich', 'width', 'height', 'overflow']; // TODO Performance improvement? - - var tmpText = new ZRText(); - - var TextStyleMixin = - /** @class */ - function () { - function TextStyleMixin() {} - /** - * Get color property or get color from option.textStyle.color - */ - // TODO Callback - - - TextStyleMixin.prototype.getTextColor = function (isEmphasis) { - var ecModel = this.ecModel; - return this.getShallow('color') || (!isEmphasis && ecModel ? ecModel.get(PATH_COLOR) : null); - }; - /** - * Create font string from fontStyle, fontWeight, fontSize, fontFamily - * @return {string} - */ - - - TextStyleMixin.prototype.getFont = function () { - return getFont({ - fontStyle: this.getShallow('fontStyle'), - fontWeight: this.getShallow('fontWeight'), - fontSize: this.getShallow('fontSize'), - fontFamily: this.getShallow('fontFamily') - }, this.ecModel); - }; - - TextStyleMixin.prototype.getTextRect = function (text) { - var style = { - text: text, - verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline') - }; - - for (var i = 0; i < textStyleParams.length; i++) { - style[textStyleParams[i]] = this.getShallow(textStyleParams[i]); - } - - tmpText.useStyle(style); - tmpText.update(); - return tmpText.getBoundingRect(); - }; - - return TextStyleMixin; - }(); - - var LINE_STYLE_KEY_MAP = [['lineWidth', 'width'], ['stroke', 'color'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'type'], ['lineDashOffset', 'dashOffset'], ['lineCap', 'cap'], ['lineJoin', 'join'], ['miterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. - // So do not transfer decal directly. - ]; - var getLineStyle = makeStyleMapper(LINE_STYLE_KEY_MAP); - - var LineStyleMixin = - /** @class */ - function () { - function LineStyleMixin() {} - - LineStyleMixin.prototype.getLineStyle = function (excludes) { - return getLineStyle(this, excludes); - }; - - return LineStyleMixin; - }(); - - var ITEM_STYLE_KEY_MAP = [['fill', 'color'], ['stroke', 'borderColor'], ['lineWidth', 'borderWidth'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'borderType'], ['lineDashOffset', 'borderDashOffset'], ['lineCap', 'borderCap'], ['lineJoin', 'borderJoin'], ['miterLimit', 'borderMiterLimit'] // Option decal is in `DecalObject` but style.decal is in `PatternObject`. - // So do not transfer decal directly. - ]; - var getItemStyle = makeStyleMapper(ITEM_STYLE_KEY_MAP); - - var ItemStyleMixin = - /** @class */ - function () { - function ItemStyleMixin() {} - - ItemStyleMixin.prototype.getItemStyle = function (excludes, includes) { - return getItemStyle(this, excludes, includes); - }; - - return ItemStyleMixin; - }(); - - var Model = - /** @class */ - function () { - function Model(option, parentModel, ecModel) { - this.parentModel = parentModel; - this.ecModel = ecModel; - this.option = option; // Simple optimization - // if (this.init) { - // if (arguments.length <= 4) { - // this.init(option, parentModel, ecModel, extraOpt); - // } - // else { - // this.init.apply(this, arguments); - // } - // } - } - - Model.prototype.init = function (option, parentModel, ecModel) {}; - /** - * Merge the input option to me. - */ - - - Model.prototype.mergeOption = function (option, ecModel) { - merge(this.option, option, true); - }; // `path` can be 'a.b.c', so the return value type have to be `ModelOption` - // TODO: TYPE strict key check? - // get(path: string | string[], ignoreParent?: boolean): ModelOption; - - - Model.prototype.get = function (path, ignoreParent) { - if (path == null) { - return this.option; - } - - return this._doGet(this.parsePath(path), !ignoreParent && this.parentModel); - }; - - Model.prototype.getShallow = function (key, ignoreParent) { - var option = this.option; - var val = option == null ? option : option[key]; - - if (val == null && !ignoreParent) { - var parentModel = this.parentModel; - - if (parentModel) { - // FIXME:TS do not know how to make it works - val = parentModel.getShallow(key); - } - } - - return val; - }; // `path` can be 'a.b.c', so the return value type have to be `Model` - // getModel(path: string | string[], parentModel?: Model): Model; - // TODO 'a.b.c' is deprecated - - - Model.prototype.getModel = function (path, parentModel) { - var hasPath = path != null; - var pathFinal = hasPath ? this.parsePath(path) : null; - var obj = hasPath ? this._doGet(pathFinal) : this.option; - parentModel = parentModel || this.parentModel && this.parentModel.getModel(this.resolveParentPath(pathFinal)); - return new Model(obj, parentModel, this.ecModel); - }; - /** - * If model has option - */ - - - Model.prototype.isEmpty = function () { - return this.option == null; - }; - - Model.prototype.restoreData = function () {}; // Pending - - - Model.prototype.clone = function () { - var Ctor = this.constructor; - return new Ctor(clone$3(this.option)); - }; // setReadOnly(properties): void { - // clazzUtil.setReadOnly(this, properties); - // } - // If path is null/undefined, return null/undefined. - - - Model.prototype.parsePath = function (path) { - if (typeof path === 'string') { - return path.split('.'); - } - - return path; - }; // Resolve path for parent. Perhaps useful when parent use a different property. - // Default to be a identity resolver. - // Can be modified to a different resolver. - - - Model.prototype.resolveParentPath = function (path) { - return path; - }; // FIXME:TS check whether put this method here - - - Model.prototype.isAnimationEnabled = function () { - if (!env.node && this.option) { - if (this.option.animation != null) { - return !!this.option.animation; - } else if (this.parentModel) { - return this.parentModel.isAnimationEnabled(); - } - } - }; - - Model.prototype._doGet = function (pathArr, parentModel) { - var obj = this.option; - - if (!pathArr) { - return obj; - } - - for (var i = 0; i < pathArr.length; i++) { - // Ignore empty - if (!pathArr[i]) { - continue; - } // obj could be number/string/... (like 0) - - - obj = obj && typeof obj === 'object' ? obj[pathArr[i]] : null; - - if (obj == null) { - break; - } - } - - if (obj == null && parentModel) { - obj = parentModel._doGet(this.resolveParentPath(pathArr), parentModel.parentModel); - } - - return obj; - }; - - return Model; - }(); // Enable Model.extend. - - - enableClassExtend(Model); - enableClassCheck(Model); - mixin(Model, LineStyleMixin); - mixin(Model, ItemStyleMixin); - mixin(Model, AreaStyleMixin); - mixin(Model, TextStyleMixin); // A random offset - - var base = Math.round(Math.random() * 10); - /** - * @public - * @param {string} type - * @return {string} - */ - - function getUID(type) { - // Considering the case of crossing js context, - // use Math.random to make id as unique as possible. - return [type || '', base++].join('_'); - } - /** - * Implements `SubTypeDefaulterManager` for `target`. - */ - - - function enableSubTypeDefaulter(target) { - var subTypeDefaulters = {}; - - target.registerSubTypeDefaulter = function (componentType, defaulter) { - var componentTypeInfo = parseClassType(componentType); - subTypeDefaulters[componentTypeInfo.main] = defaulter; - }; - - target.determineSubType = function (componentType, option) { - var type = option.type; - - if (!type) { - var componentTypeMain = parseClassType(componentType).main; - - if (target.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) { - type = subTypeDefaulters[componentTypeMain](option); - } - } - - return type; - }; - } - /** - * Implements `TopologicalTravelable` for `entity`. - * - * Topological travel on Activity Network (Activity On Vertices). - * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. - * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. - * If there is circular dependencey, Error will be thrown. - */ - - - function enableTopologicalTravel(entity, dependencyGetter) { - /** - * @param targetNameList Target Component type list. - * Can be ['aa', 'bb', 'aa.xx'] - * @param fullNameList By which we can build dependency graph. - * @param callback Params: componentType, dependencies. - * @param context Scope of callback. - */ - entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { - if (!targetNameList.length) { - return; - } - - var result = makeDepndencyGraph(fullNameList); - var graph = result.graph; - var noEntryList = result.noEntryList; - var targetNameSet = {}; - each$4(targetNameList, function (name) { - targetNameSet[name] = true; - }); - - while (noEntryList.length) { - var currComponentType = noEntryList.pop(); - var currVertex = graph[currComponentType]; - var isInTargetNameSet = !!targetNameSet[currComponentType]; - - if (isInTargetNameSet) { - callback.call(context, currComponentType, currVertex.originalDeps.slice()); - delete targetNameSet[currComponentType]; - } - - each$4(currVertex.successor, isInTargetNameSet ? removeEdgeAndAdd : removeEdge); - } - - each$4(targetNameSet, function () { - var errMsg = ''; - { - errMsg = makePrintable('Circular dependency may exists: ', targetNameSet, targetNameList, fullNameList); - } - throw new Error(errMsg); - }); - - function removeEdge(succComponentType) { - graph[succComponentType].entryCount--; - - if (graph[succComponentType].entryCount === 0) { - noEntryList.push(succComponentType); - } - } // Consider this case: legend depends on series, and we call - // chart.setOption({series: [...]}), where only series is in option. - // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will - // not be called, but only sereis.mergeOption is called. Thus legend - // have no chance to update its local record about series (like which - // name of series is available in legend). - - - function removeEdgeAndAdd(succComponentType) { - targetNameSet[succComponentType] = true; - removeEdge(succComponentType); - } - }; - - function makeDepndencyGraph(fullNameList) { - var graph = {}; - var noEntryList = []; - each$4(fullNameList, function (name) { - var thisItem = createDependencyGraphItem(graph, name); - var originalDeps = thisItem.originalDeps = dependencyGetter(name); - var availableDeps = getAvailableDependencies(originalDeps, fullNameList); - thisItem.entryCount = availableDeps.length; - - if (thisItem.entryCount === 0) { - noEntryList.push(name); - } - - each$4(availableDeps, function (dependentName) { - if (indexOf(thisItem.predecessor, dependentName) < 0) { - thisItem.predecessor.push(dependentName); - } - - var thatItem = createDependencyGraphItem(graph, dependentName); - - if (indexOf(thatItem.successor, dependentName) < 0) { - thatItem.successor.push(name); - } - }); - }); - return { - graph: graph, - noEntryList: noEntryList - }; - } - - function createDependencyGraphItem(graph, name) { - if (!graph[name]) { - graph[name] = { - predecessor: [], - successor: [] - }; - } - - return graph[name]; - } - - function getAvailableDependencies(originalDeps, fullNameList) { - var availableDeps = []; - each$4(originalDeps, function (dep) { - indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep); - }); - return availableDeps; - } - } - - function inheritDefaultOption(superOption, subOption) { - // See also `model/Component.ts#getDefaultOption` - return merge(merge({}, superOption, true), subOption, true); - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * Language: English. - */ - - - var langEN = { - time: { - month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - monthAbbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - dayOfWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayOfWeekAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] - }, - legend: { - selector: { - all: 'All', - inverse: 'Inv' - } - }, - toolbox: { - brush: { - title: { - rect: 'Box Select', - polygon: 'Lasso Select', - lineX: 'Horizontally Select', - lineY: 'Vertically Select', - keep: 'Keep Selections', - clear: 'Clear Selections' - } - }, - dataView: { - title: 'Data View', - lang: ['Data View', 'Close', 'Refresh'] - }, - dataZoom: { - title: { - zoom: 'Zoom', - back: 'Zoom Reset' - } - }, - magicType: { - title: { - line: 'Switch to Line Chart', - bar: 'Switch to Bar Chart', - stack: 'Stack', - tiled: 'Tile' - } - }, - restore: { - title: 'Restore' - }, - saveAsImage: { - title: 'Save as Image', - lang: ['Right Click to Save Image'] - } - }, - series: { - typeNames: { - pie: 'Pie chart', - bar: 'Bar chart', - line: 'Line chart', - scatter: 'Scatter plot', - effectScatter: 'Ripple scatter plot', - radar: 'Radar chart', - tree: 'Tree', - treemap: 'Treemap', - boxplot: 'Boxplot', - candlestick: 'Candlestick', - k: 'K line chart', - heatmap: 'Heat map', - map: 'Map', - parallel: 'Parallel coordinate map', - lines: 'Line graph', - graph: 'Relationship graph', - sankey: 'Sankey diagram', - funnel: 'Funnel chart', - gauge: 'Gauge', - pictorialBar: 'Pictorial bar', - themeRiver: 'Theme River Map', - sunburst: 'Sunburst', - custom: 'Custom chart', - chart: 'Chart' - } - }, - aria: { - general: { - withTitle: 'This is a chart about "{title}"', - withoutTitle: 'This is a chart' - }, - series: { - single: { - prefix: '', - withName: ' with type {seriesType} named {seriesName}.', - withoutName: ' with type {seriesType}.' - }, - multiple: { - prefix: '. It consists of {seriesCount} series count.', - withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.', - withoutName: ' The {seriesId} series is a {seriesType}.', - separator: { - middle: '', - end: '' - } - } - }, - data: { - allData: 'The data is as follows: ', - partialData: 'The first {displayCnt} items are: ', - withName: 'the data for {name} is {value}', - withoutName: '{value}', - separator: { - middle: ', ', - end: '. ' - } - } - } - }; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var langZH = { - time: { - month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], - monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], - dayOfWeek: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], - dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六'] - }, - legend: { - selector: { - all: '全选', - inverse: '反选' - } - }, - toolbox: { - brush: { - title: { - rect: '矩形选择', - polygon: '圈选', - lineX: '横向选择', - lineY: '纵向选择', - keep: '保持选择', - clear: '清除选择' - } - }, - dataView: { - title: '数据视图', - lang: ['数据视图', '关闭', '刷新'] - }, - dataZoom: { - title: { - zoom: '区域缩放', - back: '区域缩放还原' - } - }, - magicType: { - title: { - line: '切换为折线图', - bar: '切换为柱状图', - stack: '切换为堆叠', - tiled: '切换为平铺' - } - }, - restore: { - title: '还原' - }, - saveAsImage: { - title: '保存为图片', - lang: ['右键另存为图片'] - } - }, - series: { - typeNames: { - pie: '饼图', - bar: '柱状图', - line: '折线图', - scatter: '散点图', - effectScatter: '涟漪散点图', - radar: '雷达图', - tree: '树图', - treemap: '矩形树图', - boxplot: '箱型图', - candlestick: 'K线图', - k: 'K线图', - heatmap: '热力图', - map: '地图', - parallel: '平行坐标图', - lines: '线图', - graph: '关系图', - sankey: '桑基图', - funnel: '漏斗图', - gauge: '仪表盘图', - pictorialBar: '象形柱图', - themeRiver: '主题河流图', - sunburst: '旭日图', - custom: '自定义图表', - chart: '图表' - } - }, - aria: { - general: { - withTitle: '这是一个关于“{title}”的图表。', - withoutTitle: '这是一个图表,' - }, - series: { - single: { - prefix: '', - withName: '图表类型是{seriesType},表示{seriesName}。', - withoutName: '图表类型是{seriesType}。' - }, - multiple: { - prefix: '它由{seriesCount}个图表系列组成。', - withName: '第{seriesId}个系列是一个表示{seriesName}的{seriesType},', - withoutName: '第{seriesId}个系列是一个{seriesType},', - separator: { - middle: ';', - end: '。' - } - } - }, - data: { - allData: '其数据是——', - partialData: '其中,前{displayCnt}项是——', - withName: '{name}的数据是{value}', - withoutName: '{value}', - separator: { - middle: ',', - end: '' - } - } - } - }; - var LOCALE_ZH = 'ZH'; - var LOCALE_EN = 'EN'; - var DEFAULT_LOCALE = LOCALE_EN; - var localeStorage = {}; - var localeModels = {}; - var SYSTEM_LANG = !env.domSupported ? DEFAULT_LOCALE : function () { - var langStr = ( - /* eslint-disable-next-line */ - document.documentElement.lang || navigator.language || navigator.browserLanguage || DEFAULT_LOCALE).toUpperCase(); - return langStr.indexOf(LOCALE_ZH) > -1 ? LOCALE_ZH : DEFAULT_LOCALE; - }(); - - function registerLocale(locale, localeObj) { - locale = locale.toUpperCase(); - localeModels[locale] = new Model(localeObj); - localeStorage[locale] = localeObj; - } // export function getLocale(locale: string) { - // return localeStorage[locale]; - // } - - - function createLocaleObject(locale) { - if (isString(locale)) { - var localeObj = localeStorage[locale.toUpperCase()] || {}; - - if (locale === LOCALE_ZH || locale === LOCALE_EN) { - return clone$3(localeObj); - } else { - return merge(clone$3(localeObj), clone$3(localeStorage[DEFAULT_LOCALE]), false); - } - } else { - return merge(clone$3(locale), clone$3(localeStorage[DEFAULT_LOCALE]), false); - } - } - - function getLocaleModel(lang) { - return localeModels[lang]; - } - - function getDefaultLocaleModel() { - return localeModels[DEFAULT_LOCALE]; - } // Default locale - - - registerLocale(LOCALE_EN, langEN); - registerLocale(LOCALE_ZH, langZH); - var ONE_SECOND = 1000; - var ONE_MINUTE = ONE_SECOND * 60; - var ONE_HOUR = ONE_MINUTE * 60; - var ONE_DAY = ONE_HOUR * 24; - var ONE_YEAR = ONE_DAY * 365; - var defaultLeveledFormatter = { - year: '{yyyy}', - month: '{MMM}', - day: '{d}', - hour: '{HH}:{mm}', - minute: '{HH}:{mm}', - second: '{HH}:{mm}:{ss}', - millisecond: '{HH}:{mm}:{ss} {SSS}', - none: '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss} {SSS}' - }; - var fullDayFormatter = '{yyyy}-{MM}-{dd}'; - var fullLeveledFormatter = { - year: '{yyyy}', - month: '{yyyy}-{MM}', - day: fullDayFormatter, - hour: fullDayFormatter + ' ' + defaultLeveledFormatter.hour, - minute: fullDayFormatter + ' ' + defaultLeveledFormatter.minute, - second: fullDayFormatter + ' ' + defaultLeveledFormatter.second, - millisecond: defaultLeveledFormatter.none - }; - var primaryTimeUnits = ['year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond']; - var timeUnits = ['year', 'half-year', 'quarter', 'month', 'week', 'half-week', 'day', 'half-day', 'quarter-day', 'hour', 'minute', 'second', 'millisecond']; - - function pad(str, len) { - str += ''; - return '0000'.substr(0, len - str.length) + str; - } - - function getPrimaryTimeUnit(timeUnit) { - switch (timeUnit) { - case 'half-year': - case 'quarter': - return 'month'; - - case 'week': - case 'half-week': - return 'day'; - - case 'half-day': - case 'quarter-day': - return 'hour'; - - default: - // year, minutes, second, milliseconds - return timeUnit; - } - } - - function isPrimaryTimeUnit(timeUnit) { - return timeUnit === getPrimaryTimeUnit(timeUnit); - } - - function getDefaultFormatPrecisionOfInterval(timeUnit) { - switch (timeUnit) { - case 'year': - case 'month': - return 'day'; - - case 'millisecond': - return 'millisecond'; - - default: - // Also for day, hour, minute, second - return 'second'; - } - } - - function format$1( // Note: The result based on `isUTC` are totally different, which can not be just simply - // substituted by the result without `isUTC`. So we make the param `isUTC` mandatory. - time, template, isUTC, lang) { - var date = parseDate(time); - var y = date[fullYearGetterName(isUTC)](); - var M = date[monthGetterName(isUTC)]() + 1; - var q = Math.floor((M - 1) / 3) + 1; - var d = date[dateGetterName(isUTC)](); - var e = date['get' + (isUTC ? 'UTC' : '') + 'Day'](); - var H = date[hoursGetterName(isUTC)](); - var h = (H - 1) % 12 + 1; - var m = date[minutesGetterName(isUTC)](); - var s = date[secondsGetterName(isUTC)](); - var S = date[millisecondsGetterName(isUTC)](); - var localeModel = lang instanceof Model ? lang : getLocaleModel(lang || SYSTEM_LANG) || getDefaultLocaleModel(); - var timeModel = localeModel.getModel('time'); - var month = timeModel.get('month'); - var monthAbbr = timeModel.get('monthAbbr'); - var dayOfWeek = timeModel.get('dayOfWeek'); - var dayOfWeekAbbr = timeModel.get('dayOfWeekAbbr'); - return (template || '').replace(/{yyyy}/g, y + '').replace(/{yy}/g, pad(y % 100 + '', 2)).replace(/{Q}/g, q + '').replace(/{MMMM}/g, month[M - 1]).replace(/{MMM}/g, monthAbbr[M - 1]).replace(/{MM}/g, pad(M, 2)).replace(/{M}/g, M + '').replace(/{dd}/g, pad(d, 2)).replace(/{d}/g, d + '').replace(/{eeee}/g, dayOfWeek[e]).replace(/{ee}/g, dayOfWeekAbbr[e]).replace(/{e}/g, e + '').replace(/{HH}/g, pad(H, 2)).replace(/{H}/g, H + '').replace(/{hh}/g, pad(h + '', 2)).replace(/{h}/g, h + '').replace(/{mm}/g, pad(m, 2)).replace(/{m}/g, m + '').replace(/{ss}/g, pad(s, 2)).replace(/{s}/g, s + '').replace(/{SSS}/g, pad(S, 3)).replace(/{S}/g, S + ''); - } - - function leveledFormat(tick, idx, formatter, lang, isUTC) { - var template = null; - - if (isString(formatter)) { - // Single formatter for all units at all levels - template = formatter; - } else if (isFunction(formatter)) { - // Callback formatter - template = formatter(tick.value, idx, { - level: tick.level - }); - } else { - var defaults$1 = extend({}, defaultLeveledFormatter); - - if (tick.level > 0) { - for (var i = 0; i < primaryTimeUnits.length; ++i) { - defaults$1[primaryTimeUnits[i]] = "{primary|" + defaults$1[primaryTimeUnits[i]] + "}"; - } - } - - var mergedFormatter = formatter ? formatter.inherit === false ? formatter // Use formatter with bigger units - : defaults(formatter, defaults$1) : defaults$1; - var unit = getUnitFromValue(tick.value, isUTC); - - if (mergedFormatter[unit]) { - template = mergedFormatter[unit]; - } else if (mergedFormatter.inherit) { - // Unit formatter is not defined and should inherit from bigger units - var targetId = timeUnits.indexOf(unit); - - for (var i = targetId - 1; i >= 0; --i) { - if (mergedFormatter[unit]) { - template = mergedFormatter[unit]; - break; - } - } - - template = template || defaults$1.none; - } - - if (isArray(template)) { - var levelId = tick.level == null ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level; - levelId = Math.min(levelId, template.length - 1); - template = template[levelId]; - } - } - - return format$1(new Date(tick.value), template, isUTC, lang); - } - - function getUnitFromValue(value, isUTC) { - var date = parseDate(value); - var M = date[monthGetterName(isUTC)]() + 1; - var d = date[dateGetterName(isUTC)](); - var h = date[hoursGetterName(isUTC)](); - var m = date[minutesGetterName(isUTC)](); - var s = date[secondsGetterName(isUTC)](); - var S = date[millisecondsGetterName(isUTC)](); - var isSecond = S === 0; - var isMinute = isSecond && s === 0; - var isHour = isMinute && m === 0; - var isDay = isHour && h === 0; - var isMonth = isDay && d === 1; - var isYear = isMonth && M === 1; - - if (isYear) { - return 'year'; - } else if (isMonth) { - return 'month'; - } else if (isDay) { - return 'day'; - } else if (isHour) { - return 'hour'; - } else if (isMinute) { - return 'minute'; - } else if (isSecond) { - return 'second'; - } else { - return 'millisecond'; - } - } - - function getUnitValue(value, unit, isUTC) { - var date = isNumber(value) ? parseDate(value) : value; - unit = unit || getUnitFromValue(value, isUTC); - - switch (unit) { - case 'year': - return date[fullYearGetterName(isUTC)](); - - case 'half-year': - return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0; - - case 'quarter': - return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4); - - case 'month': - return date[monthGetterName(isUTC)](); - - case 'day': - return date[dateGetterName(isUTC)](); - - case 'half-day': - return date[hoursGetterName(isUTC)]() / 24; - - case 'hour': - return date[hoursGetterName(isUTC)](); - - case 'minute': - return date[minutesGetterName(isUTC)](); - - case 'second': - return date[secondsGetterName(isUTC)](); - - case 'millisecond': - return date[millisecondsGetterName(isUTC)](); - } - } - - function fullYearGetterName(isUTC) { - return isUTC ? 'getUTCFullYear' : 'getFullYear'; - } - - function monthGetterName(isUTC) { - return isUTC ? 'getUTCMonth' : 'getMonth'; - } - - function dateGetterName(isUTC) { - return isUTC ? 'getUTCDate' : 'getDate'; - } - - function hoursGetterName(isUTC) { - return isUTC ? 'getUTCHours' : 'getHours'; - } - - function minutesGetterName(isUTC) { - return isUTC ? 'getUTCMinutes' : 'getMinutes'; - } - - function secondsGetterName(isUTC) { - return isUTC ? 'getUTCSeconds' : 'getSeconds'; - } - - function millisecondsGetterName(isUTC) { - return isUTC ? 'getUTCMilliseconds' : 'getMilliseconds'; - } - - function fullYearSetterName(isUTC) { - return isUTC ? 'setUTCFullYear' : 'setFullYear'; - } - - function monthSetterName(isUTC) { - return isUTC ? 'setUTCMonth' : 'setMonth'; - } - - function dateSetterName(isUTC) { - return isUTC ? 'setUTCDate' : 'setDate'; - } - - function hoursSetterName(isUTC) { - return isUTC ? 'setUTCHours' : 'setHours'; - } - - function minutesSetterName(isUTC) { - return isUTC ? 'setUTCMinutes' : 'setMinutes'; - } - - function secondsSetterName(isUTC) { - return isUTC ? 'setUTCSeconds' : 'setSeconds'; - } - - function millisecondsSetterName(isUTC) { - return isUTC ? 'setUTCMilliseconds' : 'setMilliseconds'; - } - - function getTextRect(text, font, align, verticalAlign, padding, rich, truncate, lineHeight) { - var textEl = new ZRText({ - style: { - text: text, - font: font, - align: align, - verticalAlign: verticalAlign, - padding: padding, - rich: rich, - overflow: truncate ? 'truncate' : null, - lineHeight: lineHeight - } - }); - return textEl.getBoundingRect(); - } - /** - * Add a comma each three digit. - */ - - - function addCommas(x) { - if (!isNumeric(x)) { - return isString(x) ? x : '-'; - } - - var parts = (x + '').split('.'); - return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (parts.length > 1 ? '.' + parts[1] : ''); - } - - function toCamelCase(str, upperCaseFirst) { - str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { - return group1.toUpperCase(); - }); - - if (upperCaseFirst && str) { - str = str.charAt(0).toUpperCase() + str.slice(1); - } - - return str; - } - - var normalizeCssArray = normalizeCssArray$1; - /** - * Make value user readable for tooltip and label. - * "User readable": - * Try to not print programmer-specific text like NaN, Infinity, null, undefined. - * Avoid to display an empty string, which users can not recognize there is - * a value and it might look like a bug. - */ - - function makeValueReadable(value, valueType, useUTC) { - var USER_READABLE_DEFUALT_TIME_PATTERN = '{yyyy}-{MM}-{dd} {HH}:{mm}:{ss}'; - - function stringToUserReadable(str) { - return str && trim(str) ? str : '-'; - } - - function isNumberUserReadable(num) { - return !!(num != null && !isNaN(num) && isFinite(num)); - } - - var isTypeTime = valueType === 'time'; - var isValueDate = value instanceof Date; - - if (isTypeTime || isValueDate) { - var date = isTypeTime ? parseDate(value) : value; - - if (!isNaN(+date)) { - return format$1(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC); - } else if (isValueDate) { - return '-'; - } // In other cases, continue to try to display the value in the following code. - - } - - if (valueType === 'ordinal') { - return isStringSafe(value) ? stringToUserReadable(value) : isNumber(value) ? isNumberUserReadable(value) ? value + '' : '-' : '-'; - } // By default. - - - var numericResult = numericToNumber(value); - return isNumberUserReadable(numericResult) ? addCommas(numericResult) : isStringSafe(value) ? stringToUserReadable(value) : typeof value === 'boolean' ? value + '' : '-'; - } - - var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; - - var wrapVar = function (varName, seriesIdx) { - return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; - }; - /** - * Template formatter - * @param {Array.|Object} paramsList - */ - - - function formatTpl(tpl, paramsList, encode) { - if (!isArray(paramsList)) { - paramsList = [paramsList]; - } - - var seriesLen = paramsList.length; - - if (!seriesLen) { - return ''; - } - - var $vars = paramsList[0].$vars || []; - - for (var i = 0; i < $vars.length; i++) { - var alias = TPL_VAR_ALIAS[i]; - tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); - } - - for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { - for (var k = 0; k < $vars.length; k++) { - var val = paramsList[seriesIdx][$vars[k]]; - tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val); - } - } - - return tpl; - } - - function getTooltipMarker(inOpt, extraCssText) { - var opt = isString(inOpt) ? { - color: inOpt, - extraCssText: extraCssText - } : inOpt || {}; - var color = opt.color; - var type = opt.type; - extraCssText = opt.extraCssText; - var renderMode = opt.renderMode || 'html'; - - if (!color) { - return ''; - } - - if (renderMode === 'html') { - return type === 'subItem' ? '' : ''; - } else { - // Should better not to auto generate style name by auto-increment number here. - // Because this util is usually called in tooltip formatter, which is probably - // called repeatedly when mouse move and the auto-increment number increases fast. - // Users can make their own style name by theirselves, make it unique and readable. - var markerId = opt.markerId || 'markerX'; - return { - renderMode: renderMode, - content: '{' + markerId + '|} ', - style: type === 'subItem' ? { - width: 4, - height: 4, - borderRadius: 2, - backgroundColor: color - } : { - width: 10, - height: 10, - borderRadius: 5, - backgroundColor: color - } - }; - } - } - /** - * @deprecated Use `time/format` instead. - * ISO Date format - * @param {string} tpl - * @param {number} value - * @param {boolean} [isUTC=false] Default in local time. - * see `module:echarts/scale/Time` - * and `module:echarts/util/number#parseDate`. - * @inner - */ - - - function formatTime(tpl, value, isUTC) { - { - deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format'); - } - - if (tpl === 'week' || tpl === 'month' || tpl === 'quarter' || tpl === 'half-year' || tpl === 'year') { - tpl = 'MM-dd\nyyyy'; - } - - var date = parseDate(value); - var getUTC = isUTC ? 'getUTC' : 'get'; - var y = date[getUTC + 'FullYear'](); - var M = date[getUTC + 'Month']() + 1; - var d = date[getUTC + 'Date'](); - var h = date[getUTC + 'Hours'](); - var m = date[getUTC + 'Minutes'](); - var s = date[getUTC + 'Seconds'](); - var S = date[getUTC + 'Milliseconds'](); - tpl = tpl.replace('MM', pad(M, 2)).replace('M', M).replace('yyyy', y).replace('yy', pad(y % 100 + '', 2)).replace('dd', pad(d, 2)).replace('d', d).replace('hh', pad(h, 2)).replace('h', h).replace('mm', pad(m, 2)).replace('m', m).replace('ss', pad(s, 2)).replace('s', s).replace('SSS', pad(S, 3)); - return tpl; - } - /** - * Capital first - * @param {string} str - * @return {string} - */ - - - function capitalFirst(str) { - return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; - } - /** - * @return Never be null/undefined. - */ - - - function convertToColorString(color, defaultColor) { - defaultColor = defaultColor || 'transparent'; - return isString(color) ? color : isObject$2(color) ? color.colorStops && (color.colorStops[0] || {}).color || defaultColor : defaultColor; - } - /** - * open new tab - * @param link url - * @param target blank or self - */ - - - function windowOpen(link, target) { - /* global window */ - if (target === '_blank' || target === 'blank') { - var blank = window.open(); - blank.opener = null; - blank.location.href = link; - } else { - window.open(link, target); - } - } - - var each$3 = each$4; - /** - * @public - */ - - var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height']; - /** - * @public - */ - - var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']]; - - function boxLayout(orient, group, gap, maxWidth, maxHeight) { - var x = 0; - var y = 0; - - if (maxWidth == null) { - maxWidth = Infinity; - } - - if (maxHeight == null) { - maxHeight = Infinity; - } - - var currentLineMaxSize = 0; - group.eachChild(function (child, idx) { - var rect = child.getBoundingRect(); - var nextChild = group.childAt(idx + 1); - var nextChildRect = nextChild && nextChild.getBoundingRect(); - var nextX; - var nextY; - - if (orient === 'horizontal') { - var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0); - nextX = x + moveX; // Wrap when width exceeds maxWidth or meet a `newline` group - // FIXME compare before adding gap? - - if (nextX > maxWidth || child.newline) { - x = 0; - nextX = moveX; - y += currentLineMaxSize + gap; - currentLineMaxSize = rect.height; - } else { - // FIXME: consider rect.y is not `0`? - currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); - } - } else { - var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0); - nextY = y + moveY; // Wrap when width exceeds maxHeight or meet a `newline` group - - if (nextY > maxHeight || child.newline) { - x += currentLineMaxSize + gap; - y = 0; - nextY = moveY; - currentLineMaxSize = rect.width; - } else { - currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); - } - } - - if (child.newline) { - return; - } - - child.x = x; - child.y = y; - child.markRedraw(); - orient === 'horizontal' ? x = nextX + gap : y = nextY + gap; - }); - } - /** - * VBox or HBox layouting - * @param {string} orient - * @param {module:zrender/graphic/Group} group - * @param {number} gap - * @param {number} [width=Infinity] - * @param {number} [height=Infinity] - */ - - - var box = boxLayout; - /** - * VBox layouting - * @param {module:zrender/graphic/Group} group - * @param {number} gap - * @param {number} [width=Infinity] - * @param {number} [height=Infinity] - */ - - curry$1(boxLayout, 'vertical'); - /** - * HBox layouting - * @param {module:zrender/graphic/Group} group - * @param {number} gap - * @param {number} [width=Infinity] - * @param {number} [height=Infinity] - */ - - curry$1(boxLayout, 'horizontal'); - /** - * Parse position info. - */ - - function getLayoutRect(positionInfo, containerRect, margin) { - margin = normalizeCssArray(margin || 0); - var containerWidth = containerRect.width; - var containerHeight = containerRect.height; - var left = parsePercent(positionInfo.left, containerWidth); - var top = parsePercent(positionInfo.top, containerHeight); - var right = parsePercent(positionInfo.right, containerWidth); - var bottom = parsePercent(positionInfo.bottom, containerHeight); - var width = parsePercent(positionInfo.width, containerWidth); - var height = parsePercent(positionInfo.height, containerHeight); - var verticalMargin = margin[2] + margin[0]; - var horizontalMargin = margin[1] + margin[3]; - var aspect = positionInfo.aspect; // If width is not specified, calculate width from left and right - - if (isNaN(width)) { - width = containerWidth - right - horizontalMargin - left; - } - - if (isNaN(height)) { - height = containerHeight - bottom - verticalMargin - top; - } - - if (aspect != null) { - // If width and height are not given - // 1. Graph should not exceeds the container - // 2. Aspect must be keeped - // 3. Graph should take the space as more as possible - // FIXME - // Margin is not considered, because there is no case that both - // using margin and aspect so far. - if (isNaN(width) && isNaN(height)) { - if (aspect > containerWidth / containerHeight) { - width = containerWidth * 0.8; - } else { - height = containerHeight * 0.8; - } - } // Calculate width or height with given aspect - - - if (isNaN(width)) { - width = aspect * height; - } - - if (isNaN(height)) { - height = width / aspect; - } - } // If left is not specified, calculate left from right and width - - - if (isNaN(left)) { - left = containerWidth - right - width - horizontalMargin; - } - - if (isNaN(top)) { - top = containerHeight - bottom - height - verticalMargin; - } // Align left and top - - - switch (positionInfo.left || positionInfo.right) { - case 'center': - left = containerWidth / 2 - width / 2 - margin[3]; - break; - - case 'right': - left = containerWidth - width - horizontalMargin; - break; - } - - switch (positionInfo.top || positionInfo.bottom) { - case 'middle': - case 'center': - top = containerHeight / 2 - height / 2 - margin[0]; - break; - - case 'bottom': - top = containerHeight - height - verticalMargin; - break; - } // If something is wrong and left, top, width, height are calculated as NaN - - - left = left || 0; - top = top || 0; - - if (isNaN(width)) { - // Width may be NaN if only one value is given except width - width = containerWidth - horizontalMargin - left - (right || 0); - } - - if (isNaN(height)) { - // Height may be NaN if only one value is given except height - height = containerHeight - verticalMargin - top - (bottom || 0); - } - - var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); - rect.margin = margin; - return rect; - } - - function fetchLayoutMode(ins) { - var layoutMode = ins.layoutMode || ins.constructor.layoutMode; - return isObject$2(layoutMode) ? layoutMode : layoutMode ? { - type: layoutMode - } : null; - } - /** - * Consider Case: - * When default option has {left: 0, width: 100}, and we set {right: 0} - * through setOption or media query, using normal zrUtil.merge will cause - * {right: 0} does not take effect. - * - * @example - * ComponentModel.extend({ - * init: function () { - * ... - * let inputPositionParams = layout.getLayoutParams(option); - * this.mergeOption(inputPositionParams); - * }, - * mergeOption: function (newOption) { - * newOption && zrUtil.merge(thisOption, newOption, true); - * layout.mergeLayoutParam(thisOption, newOption); - * } - * }); - * - * @param targetOption - * @param newOption - * @param opt - */ - - - function mergeLayoutParam(targetOption, newOption, opt) { - var ignoreSize = opt && opt.ignoreSize; - !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); - var hResult = merge(HV_NAMES[0], 0); - var vResult = merge(HV_NAMES[1], 1); - copy(HV_NAMES[0], targetOption, hResult); - copy(HV_NAMES[1], targetOption, vResult); - - function merge(names, hvIdx) { - var newParams = {}; - var newValueCount = 0; - var merged = {}; - var mergedValueCount = 0; - var enoughParamNumber = 2; - each$3(names, function (name) { - merged[name] = targetOption[name]; - }); - each$3(names, function (name) { - // Consider case: newOption.width is null, which is - // set by user for removing width setting. - hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); - hasValue(newParams, name) && newValueCount++; - hasValue(merged, name) && mergedValueCount++; - }); - - if (ignoreSize[hvIdx]) { - // Only one of left/right is premitted to exist. - if (hasValue(newOption, names[1])) { - merged[names[2]] = null; - } else if (hasValue(newOption, names[2])) { - merged[names[1]] = null; - } - - return merged; - } // Case: newOption: {width: ..., right: ...}, - // or targetOption: {right: ...} and newOption: {width: ...}, - // There is no conflict when merged only has params count - // little than enoughParamNumber. - - - if (mergedValueCount === enoughParamNumber || !newValueCount) { - return merged; - } // Case: newOption: {width: ..., right: ...}, - // Than we can make sure user only want those two, and ignore - // all origin params in targetOption. - else if (newValueCount >= enoughParamNumber) { - return newParams; - } else { - // Chose another param from targetOption by priority. - for (var i = 0; i < names.length; i++) { - var name_1 = names[i]; - - if (!hasProp(newParams, name_1) && hasProp(targetOption, name_1)) { - newParams[name_1] = targetOption[name_1]; - break; - } - } - - return newParams; - } - } - - function hasProp(obj, name) { - return obj.hasOwnProperty(name); - } - - function hasValue(obj, name) { - return obj[name] != null && obj[name] !== 'auto'; - } - - function copy(names, target, source) { - each$3(names, function (name) { - target[name] = source[name]; - }); - } - } - /** - * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. - */ - - - function getLayoutParams(source) { - return copyLayoutParams({}, source); - } - /** - * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object. - * @param {Object} source - * @return {Object} Result contains those props. - */ - - - function copyLayoutParams(target, source) { - source && target && each$3(LOCATION_PARAMS, function (name) { - source.hasOwnProperty(name) && (target[name] = source[name]); - }); - return target; - } - - var inner$9 = makeInner(); - - var ComponentModel = - /** @class */ - function (_super) { - __extends(ComponentModel, _super); - - function ComponentModel(option, parentModel, ecModel) { - var _this = _super.call(this, option, parentModel, ecModel) || this; - - _this.uid = getUID('ec_cpt_model'); - return _this; - } - - ComponentModel.prototype.init = function (option, parentModel, ecModel) { - this.mergeDefaultAndTheme(option, ecModel); - }; - - ComponentModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { - var layoutMode = fetchLayoutMode(this); - var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; - var themeModel = ecModel.getTheme(); - merge(option, themeModel.get(this.mainType)); - merge(option, this.getDefaultOption()); - - if (layoutMode) { - mergeLayoutParam(option, inputPositionParams, layoutMode); - } - }; - - ComponentModel.prototype.mergeOption = function (option, ecModel) { - merge(this.option, option, true); - var layoutMode = fetchLayoutMode(this); - - if (layoutMode) { - mergeLayoutParam(this.option, option, layoutMode); - } - }; - /** - * Called immediately after `init` or `mergeOption` of this instance called. - */ - - - ComponentModel.prototype.optionUpdated = function (newCptOption, isInit) {}; - /** - * [How to declare defaultOption]: - * - * (A) If using class declaration in typescript (since echarts 5): - * ```ts - * import {ComponentOption} from '../model/option.js'; - * export interface XxxOption extends ComponentOption { - * aaa: number - * } - * export class XxxModel extends Component { - * static type = 'xxx'; - * static defaultOption: XxxOption = { - * aaa: 123 - * } - * } - * Component.registerClass(XxxModel); - * ``` - * ```ts - * import {inheritDefaultOption} from '../util/component.js'; - * import {XxxModel, XxxOption} from './XxxModel.js'; - * export interface XxxSubOption extends XxxOption { - * bbb: number - * } - * class XxxSubModel extends XxxModel { - * static defaultOption: XxxSubOption = inheritDefaultOption(XxxModel.defaultOption, { - * bbb: 456 - * }) - * fn() { - * let opt = this.getDefaultOption(); - * // opt is {aaa: 123, bbb: 456} - * } - * } - * ``` - * - * (B) If using class extend (previous approach in echarts 3 & 4): - * ```js - * let XxxComponent = Component.extend({ - * defaultOption: { - * xx: 123 - * } - * }) - * ``` - * ```js - * let XxxSubComponent = XxxComponent.extend({ - * defaultOption: { - * yy: 456 - * }, - * fn: function () { - * let opt = this.getDefaultOption(); - * // opt is {xx: 123, yy: 456} - * } - * }) - * ``` - */ - - - ComponentModel.prototype.getDefaultOption = function () { - var ctor = this.constructor; // If using class declaration, it is different to travel super class - // in legacy env and auto merge defaultOption. So if using class - // declaration, defaultOption should be merged manually. - - if (!isExtendedClass(ctor)) { - // When using ts class, defaultOption must be declared as static. - return ctor.defaultOption; - } // FIXME: remove this approach? - - - var fields = inner$9(this); - - if (!fields.defaultOption) { - var optList = []; - var clz = ctor; - - while (clz) { - var opt = clz.prototype.defaultOption; - opt && optList.push(opt); - clz = clz.superClass; - } - - var defaultOption = {}; - - for (var i = optList.length - 1; i >= 0; i--) { - defaultOption = merge(defaultOption, optList[i], true); - } - - fields.defaultOption = defaultOption; - } - - return fields.defaultOption; - }; - /** - * Notice: always force to input param `useDefault` in case that forget to consider it. - * The same behavior as `modelUtil.parseFinder`. - * - * @param useDefault In many cases like series refer axis and axis refer grid, - * If axis index / axis id not specified, use the first target as default. - * In other cases like dataZoom refer axis, if not specified, measn no refer. - */ - - - ComponentModel.prototype.getReferringComponents = function (mainType, opt) { - var indexKey = mainType + 'Index'; - var idKey = mainType + 'Id'; - return queryReferringComponents(this.ecModel, mainType, { - index: this.get(indexKey, true), - id: this.get(idKey, true) - }, opt); - }; - - ComponentModel.prototype.getBoxLayoutParams = function () { - // Consider itself having box layout configs. - var boxLayoutModel = this; - return { - left: boxLayoutModel.get('left'), - top: boxLayoutModel.get('top'), - right: boxLayoutModel.get('right'), - bottom: boxLayoutModel.get('bottom'), - width: boxLayoutModel.get('width'), - height: boxLayoutModel.get('height') - }; - }; - /** - * Get key for zlevel. - * If developers don't configure zlevel. We will assign zlevel to series based on the key. - * For example, lines with trail effect and progressive series will in an individual zlevel. - */ - - - ComponentModel.prototype.getZLevelKey = function () { - return ''; - }; - - ComponentModel.prototype.setZLevel = function (zlevel) { - this.option.zlevel = zlevel; - }; - - ComponentModel.protoInitialize = function () { - var proto = ComponentModel.prototype; - proto.type = 'component'; - proto.id = ''; - proto.name = ''; - proto.mainType = ''; - proto.subType = ''; - proto.componentIndex = 0; - }(); - - return ComponentModel; - }(Model); - - mountExtend(ComponentModel, Model); - enableClassManagement(ComponentModel); - enableSubTypeDefaulter(ComponentModel); - enableTopologicalTravel(ComponentModel, getDependencies); - - function getDependencies(componentType) { - var deps = []; - each$4(ComponentModel.getClassesByMainType(componentType), function (clz) { - deps = deps.concat(clz.dependencies || clz.prototype.dependencies || []); - }); // Ensure main type. - - deps = map$1(deps, function (type) { - return parseClassType(type).main; - }); // Hack dataset for convenience. - - if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) { - deps.unshift('dataset'); - } - - return deps; - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - var platform = ''; // Navigator not exists in node - - if (typeof navigator !== 'undefined') { - /* global navigator */ - platform = navigator.platform || ''; - } - - var decalColor = 'rgba(0, 0, 0, 0.2)'; - var globalDefault = { - darkMode: 'auto', - // backgroundColor: 'rgba(0,0,0,0)', - colorBy: 'series', - color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'], - gradientColor: ['#f6efa6', '#d88273', '#bf444c'], - aria: { - decal: { - decals: [{ - color: decalColor, - dashArrayX: [1, 0], - dashArrayY: [2, 5], - symbolSize: 1, - rotation: Math.PI / 6 - }, { - color: decalColor, - symbol: 'circle', - dashArrayX: [[8, 8], [0, 8, 8, 0]], - dashArrayY: [6, 0], - symbolSize: 0.8 - }, { - color: decalColor, - dashArrayX: [1, 0], - dashArrayY: [4, 3], - rotation: -Math.PI / 4 - }, { - color: decalColor, - dashArrayX: [[6, 6], [0, 6, 6, 0]], - dashArrayY: [6, 0] - }, { - color: decalColor, - dashArrayX: [[1, 0], [1, 6]], - dashArrayY: [1, 0, 6, 0], - rotation: Math.PI / 4 - }, { - color: decalColor, - symbol: 'triangle', - dashArrayX: [[9, 9], [0, 9, 9, 0]], - dashArrayY: [7, 2], - symbolSize: 0.75 - }] - } - }, - // If xAxis and yAxis declared, grid is created by default. - // grid: {}, - textStyle: { - // color: '#000', - // decoration: 'none', - // PENDING - fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif', - // fontFamily: 'Arial, Verdana, sans-serif', - fontSize: 12, - fontStyle: 'normal', - fontWeight: 'normal' - }, - // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/ - // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation - // Default is source-over - blendMode: null, - stateAnimation: { - duration: 300, - easing: 'cubicOut' - }, - animation: 'auto', - animationDuration: 1000, - animationDurationUpdate: 500, - animationEasing: 'cubicInOut', - animationEasingUpdate: 'cubicInOut', - animationThreshold: 2000, - // Configuration for progressive/incremental rendering - progressiveThreshold: 3000, - progressive: 400, - // Threshold of if use single hover layer to optimize. - // It is recommended that `hoverLayerThreshold` is equivalent to or less than - // `progressiveThreshold`, otherwise hover will cause restart of progressive, - // which is unexpected. - // see example . - hoverLayerThreshold: 3000, - // See: module:echarts/scale/Time - useUTC: false - }; - var VISUAL_DIMENSIONS = createHashMap(['tooltip', 'label', 'itemName', 'itemId', 'itemGroupId', 'itemChildGroupId', 'seriesName']); - var SOURCE_FORMAT_ORIGINAL = 'original'; - var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows'; - var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows'; - var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns'; - var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray'; - var SOURCE_FORMAT_UNKNOWN = 'unknown'; - var SERIES_LAYOUT_BY_COLUMN = 'column'; - var SERIES_LAYOUT_BY_ROW = 'row'; // The result of `guessOrdinal`. - - var BE_ORDINAL = { - Must: 1, - Might: 2, - Not: 3 // Other cases - - }; - var innerGlobalModel = makeInner(); - /** - * MUST be called before mergeOption of all series. - */ - - function resetSourceDefaulter(ecModel) { - // `datasetMap` is used to make default encode. - innerGlobalModel(ecModel).datasetMap = createHashMap(); - } - /** - * [The strategy of the arrengment of data dimensions for dataset]: - * "value way": all axes are non-category axes. So series one by one take - * several (the number is coordSysDims.length) dimensions from dataset. - * The result of data arrengment of data dimensions like: - * | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y | - * "category way": at least one axis is category axis. So the the first data - * dimension is always mapped to the first category axis and shared by - * all of the series. The other data dimensions are taken by series like - * "value way" does. - * The result of data arrengment of data dimensions like: - * | ser_shared_x | ser0_y | ser1_y | ser2_y | - * - * @return encode Never be `null/undefined`. - */ - - - function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) { - var encode = {}; - var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); // Currently only make default when using dataset, util more reqirements occur. - - if (!datasetModel || !coordDimensions) { - return encode; - } - - var encodeItemName = []; - var encodeSeriesName = []; - var ecModel = seriesModel.ecModel; - var datasetMap = innerGlobalModel(ecModel).datasetMap; - var key = datasetModel.uid + '_' + source.seriesLayoutBy; - var baseCategoryDimIndex; - var categoryWayValueDimStart; - coordDimensions = coordDimensions.slice(); - each$4(coordDimensions, function (coordDimInfoLoose, coordDimIdx) { - var coordDimInfo = isObject$2(coordDimInfoLoose) ? coordDimInfoLoose : coordDimensions[coordDimIdx] = { - name: coordDimInfoLoose - }; - - if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) { - baseCategoryDimIndex = coordDimIdx; - categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo); - } - - encode[coordDimInfo.name] = []; - }); - var datasetRecord = datasetMap.get(key) || datasetMap.set(key, { - categoryWayDim: categoryWayValueDimStart, - valueWayDim: 0 - }); // TODO - // Auto detect first time axis and do arrangement. - - each$4(coordDimensions, function (coordDimInfo, coordDimIdx) { - var coordDimName = coordDimInfo.name; - var count = getDataDimCountOnCoordDim(coordDimInfo); // In value way. - - if (baseCategoryDimIndex == null) { - var start = datasetRecord.valueWayDim; - pushDim(encode[coordDimName], start, count); - pushDim(encodeSeriesName, start, count); - datasetRecord.valueWayDim += count; // ??? TODO give a better default series name rule? - // especially when encode x y specified. - // consider: when multiple series share one dimension - // category axis, series name should better use - // the other dimension name. On the other hand, use - // both dimensions name. - } // In category way, the first category axis. - else if (baseCategoryDimIndex === coordDimIdx) { - pushDim(encode[coordDimName], 0, count); - pushDim(encodeItemName, 0, count); - } // In category way, the other axis. - else { - var start = datasetRecord.categoryWayDim; - pushDim(encode[coordDimName], start, count); - pushDim(encodeSeriesName, start, count); - datasetRecord.categoryWayDim += count; - } - }); - - function pushDim(dimIdxArr, idxFrom, idxCount) { - for (var i = 0; i < idxCount; i++) { - dimIdxArr.push(idxFrom + i); - } - } - - function getDataDimCountOnCoordDim(coordDimInfo) { - var dimsDef = coordDimInfo.dimsDef; - return dimsDef ? dimsDef.length : 1; - } - - encodeItemName.length && (encode.itemName = encodeItemName); - encodeSeriesName.length && (encode.seriesName = encodeSeriesName); - return encode; - } - /** - * Work for data like [{name: ..., value: ...}, ...]. - * - * @return encode Never be `null/undefined`. - */ - - - function makeSeriesEncodeForNameBased(seriesModel, source, dimCount) { - var encode = {}; - var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); // Currently only make default when using dataset, util more reqirements occur. - - if (!datasetModel) { - return encode; - } - - var sourceFormat = source.sourceFormat; - var dimensionsDefine = source.dimensionsDefine; - var potentialNameDimIndex; - - if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { - each$4(dimensionsDefine, function (dim, idx) { - if ((isObject$2(dim) ? dim.name : dim) === 'name') { - potentialNameDimIndex = idx; - } - }); - } - - var idxResult = function () { - var idxRes0 = {}; - var idxRes1 = {}; - var guessRecords = []; // 5 is an experience value. - - for (var i = 0, len = Math.min(5, dimCount); i < len; i++) { - var guessResult = doGuessOrdinal(source.data, sourceFormat, source.seriesLayoutBy, dimensionsDefine, source.startIndex, i); - guessRecords.push(guessResult); - var isPureNumber = guessResult === BE_ORDINAL.Not; // [Strategy of idxRes0]: find the first BE_ORDINAL.Not as the value dim, - // and then find a name dim with the priority: - // "BE_ORDINAL.Might|BE_ORDINAL.Must" > "other dim" > "the value dim itself". - - if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) { - idxRes0.v = i; - } - - if (idxRes0.n == null || idxRes0.n === idxRes0.v || !isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not) { - idxRes0.n = i; - } - - if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) { - return idxRes0; - } // [Strategy of idxRes1]: if idxRes0 not satisfied (that is, no BE_ORDINAL.Not), - // find the first BE_ORDINAL.Might as the value dim, - // and then find a name dim with the priority: - // "other dim" > "the value dim itself". - // That is for backward compat: number-like (e.g., `'3'`, `'55'`) can be - // treated as number. - - - if (!isPureNumber) { - if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) { - idxRes1.v = i; - } - - if (idxRes1.n == null || idxRes1.n === idxRes1.v) { - idxRes1.n = i; - } - } - } - - function fulfilled(idxResult) { - return idxResult.v != null && idxResult.n != null; - } - - return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null; - }(); - - if (idxResult) { - encode.value = [idxResult.v]; // `potentialNameDimIndex` has highest priority. - - var nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n; // By default, label uses itemName in charts. - // So we don't set encodeLabel here. - - encode.itemName = [nameDimIndex]; - encode.seriesName = [nameDimIndex]; - } - - return encode; - } - /** - * @return If return null/undefined, indicate that should not use datasetModel. - */ - - - function querySeriesUpstreamDatasetModel(seriesModel) { - // Caution: consider the scenario: - // A dataset is declared and a series is not expected to use the dataset, - // and at the beginning `setOption({series: { noData })` (just prepare other - // option but no data), then `setOption({series: {data: [...]}); In this case, - // the user should set an empty array to avoid that dataset is used by default. - var thisData = seriesModel.get('data', true); - - if (!thisData) { - return queryReferringComponents(seriesModel.ecModel, 'dataset', { - index: seriesModel.get('datasetIndex', true), - id: seriesModel.get('datasetId', true) - }, SINGLE_REFERRING).models[0]; - } - } - /** - * @return Always return an array event empty. - */ - - - function queryDatasetUpstreamDatasetModels(datasetModel) { - // Only these attributes declared, we by default reference to `datasetIndex: 0`. - // Otherwise, no reference. - if (!datasetModel.get('transform', true) && !datasetModel.get('fromTransformResult', true)) { - return []; - } - - return queryReferringComponents(datasetModel.ecModel, 'dataset', { - index: datasetModel.get('fromDatasetIndex', true), - id: datasetModel.get('fromDatasetId', true) - }, SINGLE_REFERRING).models; - } - /** - * The rule should not be complex, otherwise user might not - * be able to known where the data is wrong. - * The code is ugly, but how to make it neat? - */ - - - function guessOrdinal(source, dimIndex) { - return doGuessOrdinal(source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex); - } // dimIndex may be overflow source data. - // return {BE_ORDINAL} - - - function doGuessOrdinal(data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex) { - var result; // Experience value. - - var maxLoop = 5; - - if (isTypedArray(data)) { - return BE_ORDINAL.Not; - } // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine - // always exists in source. - - - var dimName; - var dimType; - - if (dimensionsDefine) { - var dimDefItem = dimensionsDefine[dimIndex]; - - if (isObject$2(dimDefItem)) { - dimName = dimDefItem.name; - dimType = dimDefItem.type; - } else if (isString(dimDefItem)) { - dimName = dimDefItem; - } - } - - if (dimType != null) { - return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not; - } - - if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { - var dataArrayRows = data; - - if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { - var sample = dataArrayRows[dimIndex]; - - for (var i = 0; i < (sample || []).length && i < maxLoop; i++) { - if ((result = detectValue(sample[startIndex + i])) != null) { - return result; - } - } - } else { - for (var i = 0; i < dataArrayRows.length && i < maxLoop; i++) { - var row = dataArrayRows[startIndex + i]; - - if (row && (result = detectValue(row[dimIndex])) != null) { - return result; - } - } - } - } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { - var dataObjectRows = data; - - if (!dimName) { - return BE_ORDINAL.Not; - } - - for (var i = 0; i < dataObjectRows.length && i < maxLoop; i++) { - var item = dataObjectRows[i]; - - if (item && (result = detectValue(item[dimName])) != null) { - return result; - } - } - } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { - var dataKeyedColumns = data; - - if (!dimName) { - return BE_ORDINAL.Not; - } - - var sample = dataKeyedColumns[dimName]; - - if (!sample || isTypedArray(sample)) { - return BE_ORDINAL.Not; - } - - for (var i = 0; i < sample.length && i < maxLoop; i++) { - if ((result = detectValue(sample[i])) != null) { - return result; - } - } - } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { - var dataOriginal = data; - - for (var i = 0; i < dataOriginal.length && i < maxLoop; i++) { - var item = dataOriginal[i]; - var val = getDataItemValue(item); - - if (!isArray(val)) { - return BE_ORDINAL.Not; - } - - if ((result = detectValue(val[dimIndex])) != null) { - return result; - } - } - } - - function detectValue(val) { - var beStr = isString(val); // Consider usage convenience, '1', '2' will be treated as "number". - // `isFinit('')` get `true`. - - if (val != null && isFinite(val) && val !== '') { - return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not; - } else if (beStr && val !== '-') { - return BE_ORDINAL.Must; - } - } - - return BE_ORDINAL.Not; - } - - var internalOptionCreatorMap = createHashMap(); - - function concatInternalOptions(ecModel, mainType, newCmptOptionList) { - var internalOptionCreator = internalOptionCreatorMap.get(mainType); - - if (!internalOptionCreator) { - return newCmptOptionList; - } - - var internalOptions = internalOptionCreator(ecModel); - - if (!internalOptions) { - return newCmptOptionList; - } - - { - for (var i = 0; i < internalOptions.length; i++) { - assert(isComponentIdInternal(internalOptions[i])); - } - } - return newCmptOptionList.concat(internalOptions); - } - - var innerColor = makeInner(); - makeInner(); - - var PaletteMixin = - /** @class */ - function () { - function PaletteMixin() {} - - PaletteMixin.prototype.getColorFromPalette = function (name, scope, requestNum) { - var defaultPalette = normalizeToArray(this.get('color', true)); - var layeredPalette = this.get('colorLayer', true); - return getFromPalette(this, innerColor, defaultPalette, layeredPalette, name, scope, requestNum); - }; - - PaletteMixin.prototype.clearColorPalette = function () { - clearPalette(this, innerColor); - }; - - return PaletteMixin; - }(); - - function getNearestPalette(palettes, requestColorNum) { - var paletteNum = palettes.length; // TODO palettes must be in order - - for (var i = 0; i < paletteNum; i++) { - if (palettes[i].length > requestColorNum) { - return palettes[i]; - } - } - - return palettes[paletteNum - 1]; - } - /** - * @param name MUST NOT be null/undefined. Otherwise call this function - * twise with the same parameters will get different result. - * @param scope default this. - * @return Can be null/undefined - */ - - - function getFromPalette(that, inner, defaultPalette, layeredPalette, name, scope, requestNum) { - scope = scope || that; - var scopeFields = inner(scope); - var paletteIdx = scopeFields.paletteIdx || 0; - var paletteNameMap = scopeFields.paletteNameMap = scopeFields.paletteNameMap || {}; // Use `hasOwnProperty` to avoid conflict with Object.prototype. - - if (paletteNameMap.hasOwnProperty(name)) { - return paletteNameMap[name]; - } - - var palette = requestNum == null || !layeredPalette ? defaultPalette : getNearestPalette(layeredPalette, requestNum); // In case can't find in layered color palette. - - palette = palette || defaultPalette; - - if (!palette || !palette.length) { - return; - } - - var pickedPaletteItem = palette[paletteIdx]; - - if (name) { - paletteNameMap[name] = pickedPaletteItem; - } - - scopeFields.paletteIdx = (paletteIdx + 1) % palette.length; - return pickedPaletteItem; - } - - function clearPalette(that, inner) { - inner(that).paletteIdx = 0; - inner(that).paletteNameMap = {}; - } // ----------------------- - // Internal method names: - // ----------------------- - - - var reCreateSeriesIndices; - var assertSeriesInitialized; - var initBase; - var OPTION_INNER_KEY = '\0_ec_inner'; - var OPTION_INNER_VALUE = 1; - var BUITIN_COMPONENTS_MAP = { - grid: 'GridComponent', - polar: 'PolarComponent', - geo: 'GeoComponent', - singleAxis: 'SingleAxisComponent', - parallel: 'ParallelComponent', - calendar: 'CalendarComponent', - graphic: 'GraphicComponent', - toolbox: 'ToolboxComponent', - tooltip: 'TooltipComponent', - axisPointer: 'AxisPointerComponent', - brush: 'BrushComponent', - title: 'TitleComponent', - timeline: 'TimelineComponent', - markPoint: 'MarkPointComponent', - markLine: 'MarkLineComponent', - markArea: 'MarkAreaComponent', - legend: 'LegendComponent', - dataZoom: 'DataZoomComponent', - visualMap: 'VisualMapComponent', - // aria: 'AriaComponent', - // dataset: 'DatasetComponent', - // Dependencies - xAxis: 'GridComponent', - yAxis: 'GridComponent', - angleAxis: 'PolarComponent', - radiusAxis: 'PolarComponent' - }; - var BUILTIN_CHARTS_MAP = { - line: 'LineChart', - bar: 'BarChart', - pie: 'PieChart', - scatter: 'ScatterChart', - radar: 'RadarChart', - map: 'MapChart', - tree: 'TreeChart', - treemap: 'TreemapChart', - graph: 'GraphChart', - gauge: 'GaugeChart', - funnel: 'FunnelChart', - parallel: 'ParallelChart', - sankey: 'SankeyChart', - boxplot: 'BoxplotChart', - candlestick: 'CandlestickChart', - effectScatter: 'EffectScatterChart', - lines: 'LinesChart', - heatmap: 'HeatmapChart', - pictorialBar: 'PictorialBarChart', - themeRiver: 'ThemeRiverChart', - sunburst: 'SunburstChart', - custom: 'CustomChart' - }; - var componetsMissingLogPrinted = {}; - - function checkMissingComponents(option) { - each$4(option, function (componentOption, mainType) { - if (!ComponentModel.hasClass(mainType)) { - var componentImportName = BUITIN_COMPONENTS_MAP[mainType]; - - if (componentImportName && !componetsMissingLogPrinted[componentImportName]) { - error("Component " + mainType + " is used but not imported.\nimport { " + componentImportName + " } from 'echarts/components';\necharts.use([" + componentImportName + "]);"); - componetsMissingLogPrinted[componentImportName] = true; - } - } - }); - } - - var GlobalModel = - /** @class */ - function (_super) { - __extends(GlobalModel, _super); - - function GlobalModel() { - return _super !== null && _super.apply(this, arguments) || this; - } - - GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) { - theme = theme || {}; - this.option = null; // Mark as not initialized. - - this._theme = new Model(theme); - this._locale = new Model(locale); - this._optionManager = optionManager; - }; - - GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) { - { - assert(option != null, 'option is null/undefined'); - assert(option[OPTION_INNER_KEY] !== OPTION_INNER_VALUE, 'please use chart.getOption()'); - } - var innerOpt = normalizeSetOptionInput(opts); - - this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt); - - this._resetOption(null, innerOpt); - }; - /** - * @param type null/undefined: reset all. - * 'recreate': force recreate all. - * 'timeline': only reset timeline option - * 'media': only reset media query option - * @return Whether option changed. - */ - - - GlobalModel.prototype.resetOption = function (type, opt) { - return this._resetOption(type, normalizeSetOptionInput(opt)); - }; - - GlobalModel.prototype._resetOption = function (type, opt) { - var optionChanged = false; - var optionManager = this._optionManager; - - if (!type || type === 'recreate') { - var baseOption = optionManager.mountOption(type === 'recreate'); - { - checkMissingComponents(baseOption); - } - - if (!this.option || type === 'recreate') { - initBase(this, baseOption); - } else { - this.restoreData(); - - this._mergeOption(baseOption, opt); - } - - optionChanged = true; - } - - if (type === 'timeline' || type === 'media') { - this.restoreData(); - } // By design, if `setOption(option2)` at the second time, and `option2` is a `ECUnitOption`, - // it should better not have the same props with `MediaUnit['option']`. - // Because either `option2` or `MediaUnit['option']` will be always merged to "current option" - // rather than original "baseOption". If they both override a prop, the result might be - // unexpected when media state changed after `setOption` called. - // If we really need to modify a props in each `MediaUnit['option']`, use the full version - // (`{baseOption, media}`) in `setOption`. - // For `timeline`, the case is the same. - - - if (!type || type === 'recreate' || type === 'timeline') { - var timelineOption = optionManager.getTimelineOption(this); - - if (timelineOption) { - optionChanged = true; - - this._mergeOption(timelineOption, opt); - } - } - - if (!type || type === 'recreate' || type === 'media') { - var mediaOptions = optionManager.getMediaOption(this); - - if (mediaOptions.length) { - each$4(mediaOptions, function (mediaOption) { - optionChanged = true; - - this._mergeOption(mediaOption, opt); - }, this); - } - } - - return optionChanged; - }; - - GlobalModel.prototype.mergeOption = function (option) { - this._mergeOption(option, null); - }; - - GlobalModel.prototype._mergeOption = function (newOption, opt) { - var option = this.option; - var componentsMap = this._componentsMap; - var componentsCount = this._componentsCount; - var newCmptTypes = []; - var newCmptTypeMap = createHashMap(); - var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap; - resetSourceDefaulter(this); // If no component class, merge directly. - // For example: color, animaiton options, etc. - - each$4(newOption, function (componentOption, mainType) { - if (componentOption == null) { - return; - } - - if (!ComponentModel.hasClass(mainType)) { - // globalSettingTask.dirty(); - option[mainType] = option[mainType] == null ? clone$3(componentOption) : merge(option[mainType], componentOption, true); - } else if (mainType) { - newCmptTypes.push(mainType); - newCmptTypeMap.set(mainType, true); - } - }); - - if (replaceMergeMainTypeMap) { - // If there is a mainType `xxx` in `replaceMerge` but not declared in option, - // we trade it as it is declared in option as `{xxx: []}`. Because: - // (1) for normal merge, `{xxx: null/undefined}` are the same meaning as `{xxx: []}`. - // (2) some preprocessor may convert some of `{xxx: null/undefined}` to `{xxx: []}`. - replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) { - if (ComponentModel.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) { - newCmptTypes.push(mainTypeInReplaceMerge); - newCmptTypeMap.set(mainTypeInReplaceMerge, true); - } - }); - } - - ComponentModel.topologicalTravel(newCmptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this); - - function visitComponent(mainType) { - var newCmptOptionList = concatInternalOptions(this, mainType, normalizeToArray(newOption[mainType])); - var oldCmptList = componentsMap.get(mainType); - var mergeMode = // `!oldCmptList` means init. See the comment in `mappingToExists` - !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge'; - var mappingResult = mappingToExists(oldCmptList, newCmptOptionList, mergeMode); // Set mainType and complete subType. - - setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel); // Empty it before the travel, in order to prevent `this._componentsMap` - // from being used in the `init`/`mergeOption`/`optionUpdated` of some - // components, which is probably incorrect logic. - - option[mainType] = null; - componentsMap.set(mainType, null); - componentsCount.set(mainType, 0); - var optionsByMainType = []; - var cmptsByMainType = []; - var cmptsCountByMainType = 0; - var tooltipExists; - var tooltipWarningLogged; - each$4(mappingResult, function (resultItem, index) { - var componentModel = resultItem.existing; - var newCmptOption = resultItem.newOption; - - if (!newCmptOption) { - if (componentModel) { - // Consider where is no new option and should be merged using {}, - // see removeEdgeAndAdd in topologicalTravel and - // ComponentModel.getAllClassMainTypes. - componentModel.mergeOption({}, this); - componentModel.optionUpdated({}, false); - } // If no both `resultItem.exist` and `resultItem.option`, - // either it is in `replaceMerge` and not matched by any id, - // or it has been removed in previous `replaceMerge` and left a "hole" in this component index. - - } else { - var isSeriesType = mainType === 'series'; - var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, !isSeriesType // Give a more detailed warn later if series don't exists - ); - - if (!ComponentModelClass) { - { - var subType = resultItem.keyInfo.subType; - var seriesImportName = BUILTIN_CHARTS_MAP[subType]; - - if (!componetsMissingLogPrinted[subType]) { - componetsMissingLogPrinted[subType] = true; - - if (seriesImportName) { - error("Series " + subType + " is used but not imported.\nimport { " + seriesImportName + " } from 'echarts/charts';\necharts.use([" + seriesImportName + "]);"); - } else { - error("Unknown series " + subType); - } - } - } - return; - } // TODO Before multiple tooltips get supported, we do this check to avoid unexpected exception. - - - if (mainType === 'tooltip') { - if (tooltipExists) { - { - if (!tooltipWarningLogged) { - warn('Currently only one tooltip component is allowed.'); - tooltipWarningLogged = true; - } - } - return; - } - - tooltipExists = true; - } - - if (componentModel && componentModel.constructor === ComponentModelClass) { - componentModel.name = resultItem.keyInfo.name; // componentModel.settingTask && componentModel.settingTask.dirty(); - - componentModel.mergeOption(newCmptOption, this); - componentModel.optionUpdated(newCmptOption, false); - } else { - // PENDING Global as parent ? - var extraOpt = extend({ - componentIndex: index - }, resultItem.keyInfo); - componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt); // Assign `keyInfo` - - extend(componentModel, extraOpt); - - if (resultItem.brandNew) { - componentModel.__requireNewView = true; - } - - componentModel.init(newCmptOption, this, this); // Call optionUpdated after init. - // newCmptOption has been used as componentModel.option - // and may be merged with theme and default, so pass null - // to avoid confusion. - - componentModel.optionUpdated(null, true); - } - } - - if (componentModel) { - optionsByMainType.push(componentModel.option); - cmptsByMainType.push(componentModel); - cmptsCountByMainType++; - } else { - // Always do assign to avoid elided item in array. - optionsByMainType.push(void 0); - cmptsByMainType.push(void 0); - } - }, this); - option[mainType] = optionsByMainType; - componentsMap.set(mainType, cmptsByMainType); - componentsCount.set(mainType, cmptsCountByMainType); // Backup series for filtering. - - if (mainType === 'series') { - reCreateSeriesIndices(this); - } - } // If no series declared, ensure `_seriesIndices` initialized. - - - if (!this._seriesIndices) { - reCreateSeriesIndices(this); - } - }; - /** - * Get option for output (cloned option and inner info removed) - */ - - - GlobalModel.prototype.getOption = function () { - var option = clone$3(this.option); - each$4(option, function (optInMainType, mainType) { - if (ComponentModel.hasClass(mainType)) { - var opts = normalizeToArray(optInMainType); // Inner cmpts need to be removed. - // Inner cmpts might not be at last since ec5.0, but still - // compatible for users: if inner cmpt at last, splice the returned array. - - var realLen = opts.length; - var metNonInner = false; - - for (var i = realLen - 1; i >= 0; i--) { - // Remove options with inner id. - if (opts[i] && !isComponentIdInternal(opts[i])) { - metNonInner = true; - } else { - opts[i] = null; - !metNonInner && realLen--; - } - } - - opts.length = realLen; - option[mainType] = opts; - } - }); - delete option[OPTION_INNER_KEY]; - return option; - }; - - GlobalModel.prototype.getTheme = function () { - return this._theme; - }; - - GlobalModel.prototype.getLocaleModel = function () { - return this._locale; - }; - - GlobalModel.prototype.setUpdatePayload = function (payload) { - this._payload = payload; - }; - - GlobalModel.prototype.getUpdatePayload = function () { - return this._payload; - }; - /** - * @param idx If not specified, return the first one. - */ - - - GlobalModel.prototype.getComponent = function (mainType, idx) { - var list = this._componentsMap.get(mainType); - - if (list) { - var cmpt = list[idx || 0]; - - if (cmpt) { - return cmpt; - } else if (idx == null) { - for (var i = 0; i < list.length; i++) { - if (list[i]) { - return list[i]; - } - } - } - } - }; - /** - * @return Never be null/undefined. - */ - - - GlobalModel.prototype.queryComponents = function (condition) { - var mainType = condition.mainType; - - if (!mainType) { - return []; - } - - var index = condition.index; - var id = condition.id; - var name = condition.name; - - var cmpts = this._componentsMap.get(mainType); - - if (!cmpts || !cmpts.length) { - return []; - } - - var result; - - if (index != null) { - result = []; - each$4(normalizeToArray(index), function (idx) { - cmpts[idx] && result.push(cmpts[idx]); - }); - } else if (id != null) { - result = queryByIdOrName('id', id, cmpts); - } else if (name != null) { - result = queryByIdOrName('name', name, cmpts); - } else { - // Return all non-empty components in that mainType - result = filter(cmpts, function (cmpt) { - return !!cmpt; - }); - } - - return filterBySubType(result, condition); - }; - /** - * The interface is different from queryComponents, - * which is convenient for inner usage. - * - * @usage - * let result = findComponents( - * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}} - * ); - * let result = findComponents( - * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}} - * ); - * let result = findComponents( - * {mainType: 'series', - * filter: function (model, index) {...}} - * ); - * // result like [component0, componnet1, ...] - */ - - - GlobalModel.prototype.findComponents = function (condition) { - var query = condition.query; - var mainType = condition.mainType; - var queryCond = getQueryCond(query); - var result = queryCond ? this.queryComponents(queryCond) // Retrieve all non-empty components. - : filter(this._componentsMap.get(mainType), function (cmpt) { - return !!cmpt; - }); - return doFilter(filterBySubType(result, condition)); - - function getQueryCond(q) { - var indexAttr = mainType + 'Index'; - var idAttr = mainType + 'Id'; - var nameAttr = mainType + 'Name'; - return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? { - mainType: mainType, - // subType will be filtered finally. - index: q[indexAttr], - id: q[idAttr], - name: q[nameAttr] - } : null; - } - - function doFilter(res) { - return condition.filter ? filter(res, condition.filter) : res; - } - }; - - GlobalModel.prototype.eachComponent = function (mainType, cb, context) { - var componentsMap = this._componentsMap; - - if (isFunction(mainType)) { - var ctxForAll_1 = cb; - var cbForAll_1 = mainType; - componentsMap.each(function (cmpts, componentType) { - for (var i = 0; cmpts && i < cmpts.length; i++) { - var cmpt = cmpts[i]; - cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex); - } - }); - } else { - var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject$2(mainType) ? this.findComponents(mainType) : null; - - for (var i = 0; cmpts && i < cmpts.length; i++) { - var cmpt = cmpts[i]; - cmpt && cb.call(context, cmpt, cmpt.componentIndex); - } - } - }; - /** - * Get series list before filtered by name. - */ - - - GlobalModel.prototype.getSeriesByName = function (name) { - var nameStr = convertOptionIdName(name, null); - return filter(this._componentsMap.get('series'), function (oneSeries) { - return !!oneSeries && nameStr != null && oneSeries.name === nameStr; - }); - }; - /** - * Get series list before filtered by index. - */ - - - GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) { - return this._componentsMap.get('series')[seriesIndex]; - }; - /** - * Get series list before filtered by type. - * FIXME: rename to getRawSeriesByType? - */ - - - GlobalModel.prototype.getSeriesByType = function (subType) { - return filter(this._componentsMap.get('series'), function (oneSeries) { - return !!oneSeries && oneSeries.subType === subType; - }); - }; - /** - * Get all series before filtered. - */ - - - GlobalModel.prototype.getSeries = function () { - return filter(this._componentsMap.get('series'), function (oneSeries) { - return !!oneSeries; - }); - }; - /** - * Count series before filtered. - */ - - - GlobalModel.prototype.getSeriesCount = function () { - return this._componentsCount.get('series'); - }; - /** - * After filtering, series may be different - * from raw series. - */ - - - GlobalModel.prototype.eachSeries = function (cb, context) { - assertSeriesInitialized(this); - each$4(this._seriesIndices, function (rawSeriesIndex) { - var series = this._componentsMap.get('series')[rawSeriesIndex]; - - cb.call(context, series, rawSeriesIndex); - }, this); - }; - /** - * Iterate raw series before filtered. - * - * @param {Function} cb - * @param {*} context - */ - - - GlobalModel.prototype.eachRawSeries = function (cb, context) { - each$4(this._componentsMap.get('series'), function (series) { - series && cb.call(context, series, series.componentIndex); - }); - }; - /** - * After filtering, series may be different. - * from raw series. - */ - - - GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) { - assertSeriesInitialized(this); - each$4(this._seriesIndices, function (rawSeriesIndex) { - var series = this._componentsMap.get('series')[rawSeriesIndex]; - - if (series.subType === subType) { - cb.call(context, series, rawSeriesIndex); - } - }, this); - }; - /** - * Iterate raw series before filtered of given type. - */ - - - GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) { - return each$4(this.getSeriesByType(subType), cb, context); - }; - - GlobalModel.prototype.isSeriesFiltered = function (seriesModel) { - assertSeriesInitialized(this); - return this._seriesIndicesMap.get(seriesModel.componentIndex) == null; - }; - - GlobalModel.prototype.getCurrentSeriesIndices = function () { - return (this._seriesIndices || []).slice(); - }; - - GlobalModel.prototype.filterSeries = function (cb, context) { - assertSeriesInitialized(this); - var newSeriesIndices = []; - each$4(this._seriesIndices, function (seriesRawIdx) { - var series = this._componentsMap.get('series')[seriesRawIdx]; - - cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx); - }, this); - this._seriesIndices = newSeriesIndices; - this._seriesIndicesMap = createHashMap(newSeriesIndices); - }; - - GlobalModel.prototype.restoreData = function (payload) { - reCreateSeriesIndices(this); - var componentsMap = this._componentsMap; - var componentTypes = []; - componentsMap.each(function (components, componentType) { - if (ComponentModel.hasClass(componentType)) { - componentTypes.push(componentType); - } - }); - ComponentModel.topologicalTravel(componentTypes, ComponentModel.getAllClassMainTypes(), function (componentType) { - each$4(componentsMap.get(componentType), function (component) { - if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) { - component.restoreData(); - } - }); - }); - }; - - GlobalModel.internalField = function () { - reCreateSeriesIndices = function (ecModel) { - var seriesIndices = ecModel._seriesIndices = []; - each$4(ecModel._componentsMap.get('series'), function (series) { - // series may have been removed by `replaceMerge`. - series && seriesIndices.push(series.componentIndex); - }); - ecModel._seriesIndicesMap = createHashMap(seriesIndices); - }; - - assertSeriesInitialized = function (ecModel) { - // Components that use _seriesIndices should depends on series component, - // which make sure that their initialization is after series. - { - if (!ecModel._seriesIndices) { - throw new Error('Option should contains series.'); - } - } - }; - - initBase = function (ecModel, baseOption) { - // Using OPTION_INNER_KEY to mark that this option cannot be used outside, - // i.e. `chart.setOption(chart.getModel().option);` is forbidden. - ecModel.option = {}; - ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE; // Init with series: [], in case of calling findSeries method - // before series initialized. - - ecModel._componentsMap = createHashMap({ - series: [] - }); - ecModel._componentsCount = createHashMap(); // If user spefied `option.aria`, aria will be enable. This detection should be - // performed before theme and globalDefault merge. - - var airaOption = baseOption.aria; - - if (isObject$2(airaOption) && airaOption.enabled == null) { - airaOption.enabled = true; - } - - mergeTheme(baseOption, ecModel._theme.option); // TODO Needs clone when merging to the unexisted property - - merge(baseOption, globalDefault, false); - - ecModel._mergeOption(baseOption, null); - }; - }(); - - return GlobalModel; - }(Model); - - function isNotTargetSeries(seriesModel, payload) { - if (payload) { - var index = payload.seriesIndex; - var id = payload.seriesId; - var name_1 = payload.seriesName; - return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1; - } - } - - function mergeTheme(option, theme) { - // PENDING - // NOT use `colorLayer` in theme if option has `color` - var notMergeColorLayer = option.color && !option.colorLayer; - each$4(theme, function (themeItem, name) { - if (name === 'colorLayer' && notMergeColorLayer) { - return; - } // If it is component model mainType, the model handles that merge later. - // otherwise, merge them here. - - - if (!ComponentModel.hasClass(name)) { - if (typeof themeItem === 'object') { - option[name] = !option[name] ? clone$3(themeItem) : merge(option[name], themeItem, false); - } else { - if (option[name] == null) { - option[name] = themeItem; - } - } - } - }); - } - - function queryByIdOrName(attr, idOrName, cmpts) { - // Here is a break from echarts4: string and number are - // treated as equal. - if (isArray(idOrName)) { - var keyMap_1 = createHashMap(); - each$4(idOrName, function (idOrNameItem) { - if (idOrNameItem != null) { - var idName = convertOptionIdName(idOrNameItem, null); - idName != null && keyMap_1.set(idOrNameItem, true); - } - }); - return filter(cmpts, function (cmpt) { - return cmpt && keyMap_1.get(cmpt[attr]); - }); - } else { - var idName_1 = convertOptionIdName(idOrName, null); - return filter(cmpts, function (cmpt) { - return cmpt && idName_1 != null && cmpt[attr] === idName_1; - }); - } - } - - function filterBySubType(components, condition) { - // Using hasOwnProperty for restrict. Consider - // subType is undefined in user payload. - return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) { - return cmpt && cmpt.subType === condition.subType; - }) : components; - } - - function normalizeSetOptionInput(opts) { - var replaceMergeMainTypeMap = createHashMap(); - opts && each$4(normalizeToArray(opts.replaceMerge), function (mainType) { - { - assert(ComponentModel.hasClass(mainType), '"' + mainType + '" is not valid component main type in "replaceMerge"'); - } - replaceMergeMainTypeMap.set(mainType, true); - }); - return { - replaceMergeMainTypeMap: replaceMergeMainTypeMap - }; - } - - mixin(GlobalModel, PaletteMixin); - var availableMethods = ['getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isSSR', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', // 'getModel', - 'getOption', // 'getViewOfComponentModel', - // 'getViewOfSeriesModel', - 'getId', 'updateLabelLayout']; - - var ExtensionAPI = - /** @class */ - function () { - function ExtensionAPI(ecInstance) { - each$4(availableMethods, function (methodName) { - this[methodName] = bind$1(ecInstance[methodName], ecInstance); - }, this); - } - - return ExtensionAPI; - }(); - - var coordinateSystemCreators = {}; - - var CoordinateSystemManager = - /** @class */ - function () { - function CoordinateSystemManager() { - this._coordinateSystems = []; - } - - CoordinateSystemManager.prototype.create = function (ecModel, api) { - var coordinateSystems = []; - each$4(coordinateSystemCreators, function (creator, type) { - var list = creator.create(ecModel, api); - coordinateSystems = coordinateSystems.concat(list || []); - }); - this._coordinateSystems = coordinateSystems; - }; - - CoordinateSystemManager.prototype.update = function (ecModel, api) { - each$4(this._coordinateSystems, function (coordSys) { - coordSys.update && coordSys.update(ecModel, api); - }); - }; - - CoordinateSystemManager.prototype.getCoordinateSystems = function () { - return this._coordinateSystems.slice(); - }; - - CoordinateSystemManager.register = function (type, creator) { - coordinateSystemCreators[type] = creator; - }; - - CoordinateSystemManager.get = function (type) { - return coordinateSystemCreators[type]; - }; - - return CoordinateSystemManager; - }(); - - var QUERY_REG = /^(min|max)?(.+)$/; // Key: mainType - // type FakeComponentsMap = HashMap<(MappingExistingItem & { subType: string })[]>; - - /** - * TERM EXPLANATIONS: - * See `ECOption` and `ECUnitOption` in `src/util/types.ts`. - */ - - var OptionManager = - /** @class */ - function () { - // timeline.notMerge is not supported in ec3. Firstly there is rearly - // case that notMerge is needed. Secondly supporting 'notMerge' requires - // rawOption cloned and backuped when timeline changed, which does no - // good to performance. What's more, that both timeline and setOption - // method supply 'notMerge' brings complex and some problems. - // Consider this case: - // (step1) chart.setOption({timeline: {notMerge: false}, ...}, false); - // (step2) chart.setOption({timeline: {notMerge: true}, ...}, false); - function OptionManager(api) { - this._timelineOptions = []; - this._mediaList = []; - /** - * -1, means default. - * empty means no media. - */ - - this._currentMediaIndices = []; - this._api = api; - } - - OptionManager.prototype.setOption = function (rawOption, optionPreprocessorFuncs, opt) { - if (rawOption) { - // That set dat primitive is dangerous if user reuse the data when setOption again. - each$4(normalizeToArray(rawOption.series), function (series) { - series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data); - }); - each$4(normalizeToArray(rawOption.dataset), function (dataset) { - dataset && dataset.source && isTypedArray(dataset.source) && setAsPrimitive(dataset.source); - }); - } // Caution: some series modify option data, if do not clone, - // it should ensure that the repeat modify correctly - // (create a new object when modify itself). - - - rawOption = clone$3(rawOption); // FIXME - // If some property is set in timeline options or media option but - // not set in baseOption, a warning should be given. - - var optionBackup = this._optionBackup; - var newParsedOption = parseRawOption(rawOption, optionPreprocessorFuncs, !optionBackup); - this._newBaseOption = newParsedOption.baseOption; // For setOption at second time (using merge mode); - - if (optionBackup) { - // FIXME - // the restore merge solution is essentially incorrect. - // the mapping can not be 100% consistent with ecModel, which probably brings - // potential bug! - // The first merge is delayed, because in most cases, users do not call `setOption` twice. - // let fakeCmptsMap = this._fakeCmptsMap; - // if (!fakeCmptsMap) { - // fakeCmptsMap = this._fakeCmptsMap = createHashMap(); - // mergeToBackupOption(fakeCmptsMap, null, optionBackup.baseOption, null); - // } - // mergeToBackupOption( - // fakeCmptsMap, optionBackup.baseOption, newParsedOption.baseOption, opt - // ); - // For simplicity, timeline options and media options do not support merge, - // that is, if you `setOption` twice and both has timeline options, the latter - // timeline options will not be merged to the former, but just substitute them. - if (newParsedOption.timelineOptions.length) { - optionBackup.timelineOptions = newParsedOption.timelineOptions; - } - - if (newParsedOption.mediaList.length) { - optionBackup.mediaList = newParsedOption.mediaList; - } - - if (newParsedOption.mediaDefault) { - optionBackup.mediaDefault = newParsedOption.mediaDefault; - } - } else { - this._optionBackup = newParsedOption; - } - }; - - OptionManager.prototype.mountOption = function (isRecreate) { - var optionBackup = this._optionBackup; - this._timelineOptions = optionBackup.timelineOptions; - this._mediaList = optionBackup.mediaList; - this._mediaDefault = optionBackup.mediaDefault; - this._currentMediaIndices = []; - return clone$3(isRecreate // this._optionBackup.baseOption, which is created at the first `setOption` - // called, and is merged into every new option by inner method `mergeToBackupOption` - // each time `setOption` called, can be only used in `isRecreate`, because - // its reliability is under suspicion. In other cases option merge is - // performed by `model.mergeOption`. - ? optionBackup.baseOption : this._newBaseOption); - }; - - OptionManager.prototype.getTimelineOption = function (ecModel) { - var option; - var timelineOptions = this._timelineOptions; - - if (timelineOptions.length) { - // getTimelineOption can only be called after ecModel inited, - // so we can get currentIndex from timelineModel. - var timelineModel = ecModel.getComponent('timeline'); - - if (timelineModel) { - option = clone$3( // FIXME:TS as TimelineModel or quivlant interface - timelineOptions[timelineModel.getCurrentIndex()]); - } - } - - return option; - }; - - OptionManager.prototype.getMediaOption = function (ecModel) { - var ecWidth = this._api.getWidth(); - - var ecHeight = this._api.getHeight(); - - var mediaList = this._mediaList; - var mediaDefault = this._mediaDefault; - var indices = []; - var result = []; // No media defined. - - if (!mediaList.length && !mediaDefault) { - return result; - } // Multi media may be applied, the latter defined media has higher priority. - - - for (var i = 0, len = mediaList.length; i < len; i++) { - if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) { - indices.push(i); - } - } // FIXME - // Whether mediaDefault should force users to provide? Otherwise - // the change by media query can not be recorvered. - - - if (!indices.length && mediaDefault) { - indices = [-1]; - } - - if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) { - result = map$1(indices, function (index) { - return clone$3(index === -1 ? mediaDefault.option : mediaList[index].option); - }); - } // Otherwise return nothing. - - - this._currentMediaIndices = indices; - return result; - }; - - return OptionManager; - }(); - /** - * [RAW_OPTION_PATTERNS] - * (Note: "series: []" represents all other props in `ECUnitOption`) - * - * (1) No prop "baseOption" declared: - * Root option is used as "baseOption" (except prop "options" and "media"). - * ```js - * option = { - * series: [], - * timeline: {}, - * options: [], - * }; - * option = { - * series: [], - * media: {}, - * }; - * option = { - * series: [], - * timeline: {}, - * options: [], - * media: {}, - * } - * ``` - * - * (2) Prop "baseOption" declared: - * If "baseOption" declared, `ECUnitOption` props can only be declared - * inside "baseOption" except prop "timeline" (compat ec2). - * ```js - * option = { - * baseOption: { - * timeline: {}, - * series: [], - * }, - * options: [] - * }; - * option = { - * baseOption: { - * series: [], - * }, - * media: [] - * }; - * option = { - * baseOption: { - * timeline: {}, - * series: [], - * }, - * options: [] - * media: [] - * }; - * option = { - * // ec3 compat ec2: allow (only) `timeline` declared - * // outside baseOption. Keep this setting for compat. - * timeline: {}, - * baseOption: { - * series: [], - * }, - * options: [], - * media: [] - * }; - * ``` - */ - - - function parseRawOption( // `rawOption` May be modified - rawOption, optionPreprocessorFuncs, isNew) { - var mediaList = []; - var mediaDefault; - var baseOption; - var declaredBaseOption = rawOption.baseOption; // Compatible with ec2, [RAW_OPTION_PATTERNS] above. - - var timelineOnRoot = rawOption.timeline; - var timelineOptionsOnRoot = rawOption.options; - var mediaOnRoot = rawOption.media; - var hasMedia = !!rawOption.media; - var hasTimeline = !!(timelineOptionsOnRoot || timelineOnRoot || declaredBaseOption && declaredBaseOption.timeline); - - if (declaredBaseOption) { - baseOption = declaredBaseOption; // For merge option. - - if (!baseOption.timeline) { - baseOption.timeline = timelineOnRoot; - } - } // For convenience, enable to use the root option as the `baseOption`: - // `{ ...normalOptionProps, media: [{ ... }, { ... }] }` - else { - if (hasTimeline || hasMedia) { - rawOption.options = rawOption.media = null; - } - - baseOption = rawOption; - } - - if (hasMedia) { - if (isArray(mediaOnRoot)) { - each$4(mediaOnRoot, function (singleMedia) { - { - // Real case of wrong config. - if (singleMedia && !singleMedia.option && isObject$2(singleMedia.query) && isObject$2(singleMedia.query.option)) { - error('Illegal media option. Must be like { media: [ { query: {}, option: {} } ] }'); - } - } - - if (singleMedia && singleMedia.option) { - if (singleMedia.query) { - mediaList.push(singleMedia); - } else if (!mediaDefault) { - // Use the first media default. - mediaDefault = singleMedia; - } - } - }); - } else { - { - // Real case of wrong config. - error('Illegal media option. Must be an array. Like { media: [ {...}, {...} ] }'); - } - } - } - - doPreprocess(baseOption); - each$4(timelineOptionsOnRoot, function (option) { - return doPreprocess(option); - }); - each$4(mediaList, function (media) { - return doPreprocess(media.option); - }); - - function doPreprocess(option) { - each$4(optionPreprocessorFuncs, function (preProcess) { - preProcess(option, isNew); - }); - } - - return { - baseOption: baseOption, - timelineOptions: timelineOptionsOnRoot || [], - mediaDefault: mediaDefault, - mediaList: mediaList - }; - } - /** - * @see - * Support: width, height, aspectRatio - * Can use max or min as prefix. - */ - - - function applyMediaQuery(query, ecWidth, ecHeight) { - var realMap = { - width: ecWidth, - height: ecHeight, - aspectratio: ecWidth / ecHeight // lower case for convenience. - - }; - var applicable = true; - each$4(query, function (value, attr) { - var matched = attr.match(QUERY_REG); - - if (!matched || !matched[1] || !matched[2]) { - return; - } - - var operator = matched[1]; - var realAttr = matched[2].toLowerCase(); - - if (!compare(realMap[realAttr], value, operator)) { - applicable = false; - } - }); - return applicable; - } - - function compare(real, expect, operator) { - if (operator === 'min') { - return real >= expect; - } else if (operator === 'max') { - return real <= expect; - } else { - // Equals - return real === expect; - } - } - - function indicesEquals(indices1, indices2) { - // indices is always order by asc and has only finite number. - return indices1.join(',') === indices2.join(','); - } - - var each$2 = each$4; - var isObject$1 = isObject$2; - var POSSIBLE_STYLES = ['areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', 'chordStyle', 'label', 'labelLine']; - - function compatEC2ItemStyle(opt) { - var itemStyleOpt = opt && opt.itemStyle; - - if (!itemStyleOpt) { - return; - } - - for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) { - var styleName = POSSIBLE_STYLES[i]; - var normalItemStyleOpt = itemStyleOpt.normal; - var emphasisItemStyleOpt = itemStyleOpt.emphasis; - - if (normalItemStyleOpt && normalItemStyleOpt[styleName]) { - { - deprecateReplaceLog("itemStyle.normal." + styleName, styleName); - } - opt[styleName] = opt[styleName] || {}; - - if (!opt[styleName].normal) { - opt[styleName].normal = normalItemStyleOpt[styleName]; - } else { - merge(opt[styleName].normal, normalItemStyleOpt[styleName]); - } - - normalItemStyleOpt[styleName] = null; - } - - if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) { - { - deprecateReplaceLog("itemStyle.emphasis." + styleName, "emphasis." + styleName); - } - opt[styleName] = opt[styleName] || {}; - - if (!opt[styleName].emphasis) { - opt[styleName].emphasis = emphasisItemStyleOpt[styleName]; - } else { - merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]); - } - - emphasisItemStyleOpt[styleName] = null; - } - } - } - - function convertNormalEmphasis(opt, optType, useExtend) { - if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) { - var normalOpt = opt[optType].normal; - var emphasisOpt = opt[optType].emphasis; - - if (normalOpt) { - { - // eslint-disable-next-line max-len - deprecateLog("'normal' hierarchy in " + optType + " has been removed since 4.0. All style properties are configured in " + optType + " directly now."); - } // Timeline controlStyle has other properties besides normal and emphasis - - if (useExtend) { - opt[optType].normal = opt[optType].emphasis = null; - defaults(opt[optType], normalOpt); - } else { - opt[optType] = normalOpt; - } - } - - if (emphasisOpt) { - { - deprecateLog(optType + ".emphasis has been changed to emphasis." + optType + " since 4.0"); - } - opt.emphasis = opt.emphasis || {}; - opt.emphasis[optType] = emphasisOpt; // Also compat the case user mix the style and focus together in ec3 style - // for example: { itemStyle: { normal: {}, emphasis: {focus, shadowBlur} } } - - if (emphasisOpt.focus) { - opt.emphasis.focus = emphasisOpt.focus; - } - - if (emphasisOpt.blurScope) { - opt.emphasis.blurScope = emphasisOpt.blurScope; - } - } - } - } - - function removeEC3NormalStatus(opt) { - convertNormalEmphasis(opt, 'itemStyle'); - convertNormalEmphasis(opt, 'lineStyle'); - convertNormalEmphasis(opt, 'areaStyle'); - convertNormalEmphasis(opt, 'label'); - convertNormalEmphasis(opt, 'labelLine'); // treemap - - convertNormalEmphasis(opt, 'upperLabel'); // graph - - convertNormalEmphasis(opt, 'edgeLabel'); - } - - function compatTextStyle(opt, propName) { - // Check whether is not object (string\null\undefined ...) - var labelOptSingle = isObject$1(opt) && opt[propName]; - var textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle; - - if (textStyle) { - { - // eslint-disable-next-line max-len - deprecateLog("textStyle hierarchy in " + propName + " has been removed since 4.0. All textStyle properties are configured in " + propName + " directly now."); - } - - for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) { - var textPropName = TEXT_STYLE_OPTIONS[i]; - - if (textStyle.hasOwnProperty(textPropName)) { - labelOptSingle[textPropName] = textStyle[textPropName]; - } - } - } - } - - function compatEC3CommonStyles(opt) { - if (opt) { - removeEC3NormalStatus(opt); - compatTextStyle(opt, 'label'); - opt.emphasis && compatTextStyle(opt.emphasis, 'label'); - } - } - - function processSeries(seriesOpt) { - if (!isObject$1(seriesOpt)) { - return; - } - - compatEC2ItemStyle(seriesOpt); - removeEC3NormalStatus(seriesOpt); - compatTextStyle(seriesOpt, 'label'); // treemap - - compatTextStyle(seriesOpt, 'upperLabel'); // graph - - compatTextStyle(seriesOpt, 'edgeLabel'); - - if (seriesOpt.emphasis) { - compatTextStyle(seriesOpt.emphasis, 'label'); // treemap - - compatTextStyle(seriesOpt.emphasis, 'upperLabel'); // graph - - compatTextStyle(seriesOpt.emphasis, 'edgeLabel'); - } - - var markPoint = seriesOpt.markPoint; - - if (markPoint) { - compatEC2ItemStyle(markPoint); - compatEC3CommonStyles(markPoint); - } - - var markLine = seriesOpt.markLine; - - if (markLine) { - compatEC2ItemStyle(markLine); - compatEC3CommonStyles(markLine); - } - - var markArea = seriesOpt.markArea; - - if (markArea) { - compatEC3CommonStyles(markArea); - } - - var data = seriesOpt.data; // Break with ec3: if `setOption` again, there may be no `type` in option, - // then the backward compat based on option type will not be performed. - - if (seriesOpt.type === 'graph') { - data = data || seriesOpt.nodes; - var edgeData = seriesOpt.links || seriesOpt.edges; - - if (edgeData && !isTypedArray(edgeData)) { - for (var i = 0; i < edgeData.length; i++) { - compatEC3CommonStyles(edgeData[i]); - } - } - - each$4(seriesOpt.categories, function (opt) { - removeEC3NormalStatus(opt); - }); - } - - if (data && !isTypedArray(data)) { - for (var i = 0; i < data.length; i++) { - compatEC3CommonStyles(data[i]); - } - } // mark point data - - - markPoint = seriesOpt.markPoint; - - if (markPoint && markPoint.data) { - var mpData = markPoint.data; - - for (var i = 0; i < mpData.length; i++) { - compatEC3CommonStyles(mpData[i]); - } - } // mark line data - - - markLine = seriesOpt.markLine; - - if (markLine && markLine.data) { - var mlData = markLine.data; - - for (var i = 0; i < mlData.length; i++) { - if (isArray(mlData[i])) { - compatEC3CommonStyles(mlData[i][0]); - compatEC3CommonStyles(mlData[i][1]); - } else { - compatEC3CommonStyles(mlData[i]); - } - } - } // Series - - - if (seriesOpt.type === 'gauge') { - compatTextStyle(seriesOpt, 'axisLabel'); - compatTextStyle(seriesOpt, 'title'); - compatTextStyle(seriesOpt, 'detail'); - } else if (seriesOpt.type === 'treemap') { - convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle'); - each$4(seriesOpt.levels, function (opt) { - removeEC3NormalStatus(opt); - }); - } else if (seriesOpt.type === 'tree') { - removeEC3NormalStatus(seriesOpt.leaves); - } // sunburst starts from ec4, so it does not need to compat levels. - - } - - function toArr(o) { - return isArray(o) ? o : o ? [o] : []; - } - - function toObj(o) { - return (isArray(o) ? o[0] : o) || {}; - } - - function globalCompatStyle(option, isTheme) { - each$2(toArr(option.series), function (seriesOpt) { - isObject$1(seriesOpt) && processSeries(seriesOpt); - }); - var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar']; - isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis'); - each$2(axes, function (axisName) { - each$2(toArr(option[axisName]), function (axisOpt) { - if (axisOpt) { - compatTextStyle(axisOpt, 'axisLabel'); - compatTextStyle(axisOpt.axisPointer, 'label'); - } - }); - }); - each$2(toArr(option.parallel), function (parallelOpt) { - var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault; - compatTextStyle(parallelAxisDefault, 'axisLabel'); - compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label'); - }); - each$2(toArr(option.calendar), function (calendarOpt) { - convertNormalEmphasis(calendarOpt, 'itemStyle'); - compatTextStyle(calendarOpt, 'dayLabel'); - compatTextStyle(calendarOpt, 'monthLabel'); - compatTextStyle(calendarOpt, 'yearLabel'); - }); // radar.name.textStyle - - each$2(toArr(option.radar), function (radarOpt) { - compatTextStyle(radarOpt, 'name'); // Use axisName instead of name because component has name property - - if (radarOpt.name && radarOpt.axisName == null) { - radarOpt.axisName = radarOpt.name; - delete radarOpt.name; - { - deprecateLog('name property in radar component has been changed to axisName'); - } - } - - if (radarOpt.nameGap != null && radarOpt.axisNameGap == null) { - radarOpt.axisNameGap = radarOpt.nameGap; - delete radarOpt.nameGap; - { - deprecateLog('nameGap property in radar component has been changed to axisNameGap'); - } - } - - { - each$2(radarOpt.indicator, function (indicatorOpt) { - if (indicatorOpt.text) { - deprecateReplaceLog('text', 'name', 'radar.indicator'); - } - }); - } - }); - each$2(toArr(option.geo), function (geoOpt) { - if (isObject$1(geoOpt)) { - compatEC3CommonStyles(geoOpt); - each$2(toArr(geoOpt.regions), function (regionObj) { - compatEC3CommonStyles(regionObj); - }); - } - }); - each$2(toArr(option.timeline), function (timelineOpt) { - compatEC3CommonStyles(timelineOpt); - convertNormalEmphasis(timelineOpt, 'label'); - convertNormalEmphasis(timelineOpt, 'itemStyle'); - convertNormalEmphasis(timelineOpt, 'controlStyle', true); - var data = timelineOpt.data; - isArray(data) && each$4(data, function (item) { - if (isObject$2(item)) { - convertNormalEmphasis(item, 'label'); - convertNormalEmphasis(item, 'itemStyle'); - } - }); - }); - each$2(toArr(option.toolbox), function (toolboxOpt) { - convertNormalEmphasis(toolboxOpt, 'iconStyle'); - each$2(toolboxOpt.feature, function (featureOpt) { - convertNormalEmphasis(featureOpt, 'iconStyle'); - }); - }); - compatTextStyle(toObj(option.axisPointer), 'label'); - compatTextStyle(toObj(option.tooltip).axisPointer, 'label'); // Clean logs - // storedLogs = {}; - } - - function get(opt, path) { - var pathArr = path.split(','); - var obj = opt; - - for (var i = 0; i < pathArr.length; i++) { - obj = obj && obj[pathArr[i]]; - - if (obj == null) { - break; - } - } - - return obj; - } - - function set(opt, path, val, overwrite) { - var pathArr = path.split(','); - var obj = opt; - var key; - var i = 0; - - for (; i < pathArr.length - 1; i++) { - key = pathArr[i]; - - if (obj[key] == null) { - obj[key] = {}; - } - - obj = obj[key]; - } - - if (overwrite || obj[pathArr[i]] == null) { - obj[pathArr[i]] = val; - } - } - - function compatLayoutProperties(option) { - option && each$4(LAYOUT_PROPERTIES, function (prop) { - if (prop[0] in option && !(prop[1] in option)) { - option[prop[1]] = option[prop[0]]; - } - }); - } - - var LAYOUT_PROPERTIES = [['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']]; - var COMPATITABLE_COMPONENTS = ['grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline']; - var BAR_ITEM_STYLE_MAP = [['borderRadius', 'barBorderRadius'], ['borderColor', 'barBorderColor'], ['borderWidth', 'barBorderWidth']]; - - function compatBarItemStyle(option) { - var itemStyle = option && option.itemStyle; - - if (itemStyle) { - for (var i = 0; i < BAR_ITEM_STYLE_MAP.length; i++) { - var oldName = BAR_ITEM_STYLE_MAP[i][1]; - var newName = BAR_ITEM_STYLE_MAP[i][0]; - - if (itemStyle[oldName] != null) { - itemStyle[newName] = itemStyle[oldName]; - { - deprecateReplaceLog(oldName, newName); - } - } - } - } - } - - function compatPieLabel(option) { - if (!option) { - return; - } - - if (option.alignTo === 'edge' && option.margin != null && option.edgeDistance == null) { - { - deprecateReplaceLog('label.margin', 'label.edgeDistance', 'pie'); - } - option.edgeDistance = option.margin; - } - } - - function compatSunburstState(option) { - if (!option) { - return; - } - - if (option.downplay && !option.blur) { - option.blur = option.downplay; - { - deprecateReplaceLog('downplay', 'blur', 'sunburst'); - } - } - } - - function compatGraphFocus(option) { - if (!option) { - return; - } - - if (option.focusNodeAdjacency != null) { - option.emphasis = option.emphasis || {}; - - if (option.emphasis.focus == null) { - { - deprecateReplaceLog('focusNodeAdjacency', 'emphasis: { focus: \'adjacency\'}', 'graph/sankey'); - } - option.emphasis.focus = 'adjacency'; - } - } - } - - function traverseTree(data, cb) { - if (data) { - for (var i = 0; i < data.length; i++) { - cb(data[i]); - data[i] && traverseTree(data[i].children, cb); - } - } - } - - function globalBackwardCompat(option, isTheme) { - globalCompatStyle(option, isTheme); // Make sure series array for model initialization. - - option.series = normalizeToArray(option.series); - each$4(option.series, function (seriesOpt) { - if (!isObject$2(seriesOpt)) { - return; - } - - var seriesType = seriesOpt.type; - - if (seriesType === 'line') { - if (seriesOpt.clipOverflow != null) { - seriesOpt.clip = seriesOpt.clipOverflow; - { - deprecateReplaceLog('clipOverflow', 'clip', 'line'); - } - } - } else if (seriesType === 'pie' || seriesType === 'gauge') { - if (seriesOpt.clockWise != null) { - seriesOpt.clockwise = seriesOpt.clockWise; - { - deprecateReplaceLog('clockWise', 'clockwise'); - } - } - - compatPieLabel(seriesOpt.label); - var data = seriesOpt.data; - - if (data && !isTypedArray(data)) { - for (var i = 0; i < data.length; i++) { - compatPieLabel(data[i]); - } - } - - if (seriesOpt.hoverOffset != null) { - seriesOpt.emphasis = seriesOpt.emphasis || {}; - - if (seriesOpt.emphasis.scaleSize = null) { - { - deprecateReplaceLog('hoverOffset', 'emphasis.scaleSize'); - } - seriesOpt.emphasis.scaleSize = seriesOpt.hoverOffset; - } - } - } else if (seriesType === 'gauge') { - var pointerColor = get(seriesOpt, 'pointer.color'); - pointerColor != null && set(seriesOpt, 'itemStyle.color', pointerColor); - } else if (seriesType === 'bar') { - compatBarItemStyle(seriesOpt); - compatBarItemStyle(seriesOpt.backgroundStyle); - compatBarItemStyle(seriesOpt.emphasis); - var data = seriesOpt.data; - - if (data && !isTypedArray(data)) { - for (var i = 0; i < data.length; i++) { - if (typeof data[i] === 'object') { - compatBarItemStyle(data[i]); - compatBarItemStyle(data[i] && data[i].emphasis); - } - } - } - } else if (seriesType === 'sunburst') { - var highlightPolicy = seriesOpt.highlightPolicy; - - if (highlightPolicy) { - seriesOpt.emphasis = seriesOpt.emphasis || {}; - - if (!seriesOpt.emphasis.focus) { - seriesOpt.emphasis.focus = highlightPolicy; - { - deprecateReplaceLog('highlightPolicy', 'emphasis.focus', 'sunburst'); - } - } - } - - compatSunburstState(seriesOpt); - traverseTree(seriesOpt.data, compatSunburstState); - } else if (seriesType === 'graph' || seriesType === 'sankey') { - compatGraphFocus(seriesOpt); // TODO nodes, edges? - } else if (seriesType === 'map') { - if (seriesOpt.mapType && !seriesOpt.map) { - { - deprecateReplaceLog('mapType', 'map', 'map'); - } - seriesOpt.map = seriesOpt.mapType; - } - - if (seriesOpt.mapLocation) { - { - deprecateLog('`mapLocation` is not used anymore.'); - } - defaults(seriesOpt, seriesOpt.mapLocation); - } - } - - if (seriesOpt.hoverAnimation != null) { - seriesOpt.emphasis = seriesOpt.emphasis || {}; - - if (seriesOpt.emphasis && seriesOpt.emphasis.scale == null) { - { - deprecateReplaceLog('hoverAnimation', 'emphasis.scale'); - } - seriesOpt.emphasis.scale = seriesOpt.hoverAnimation; - } - } - - compatLayoutProperties(seriesOpt); - }); // dataRange has changed to visualMap - - if (option.dataRange) { - option.visualMap = option.dataRange; - } - - each$4(COMPATITABLE_COMPONENTS, function (componentName) { - var options = option[componentName]; - - if (options) { - if (!isArray(options)) { - options = [options]; - } - - each$4(options, function (option) { - compatLayoutProperties(option); - }); - } - }); - } // (1) [Caution]: the logic is correct based on the premises: - // data processing stage is blocked in stream. - // See - // (2) Only register once when import repeatedly. - // Should be executed after series is filtered and before stack calculation. - - - function dataStack$1(ecModel) { - var stackInfoMap = createHashMap(); - ecModel.eachSeries(function (seriesModel) { - var stack = seriesModel.get('stack'); // Compatible: when `stack` is set as '', do not stack. - - if (stack) { - var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); - var data = seriesModel.getData(); - var stackInfo = { - // Used for calculate axis extent automatically. - // TODO: Type getCalculationInfo return more specific type? - stackResultDimension: data.getCalculationInfo('stackResultDimension'), - stackedOverDimension: data.getCalculationInfo('stackedOverDimension'), - stackedDimension: data.getCalculationInfo('stackedDimension'), - stackedByDimension: data.getCalculationInfo('stackedByDimension'), - isStackedByIndex: data.getCalculationInfo('isStackedByIndex'), - data: data, - seriesModel: seriesModel - }; // If stacked on axis that do not support data stack. - - if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) { - return; - } - - stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel); - stackInfoList.push(stackInfo); - } - }); - stackInfoMap.each(calculateStack); - } - - function calculateStack(stackInfoList) { - each$4(stackInfoList, function (targetStackInfo, idxInStack) { - var resultVal = []; - var resultNaN = [NaN, NaN]; - var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; - var targetData = targetStackInfo.data; - var isStackedByIndex = targetStackInfo.isStackedByIndex; - var stackStrategy = targetStackInfo.seriesModel.get('stackStrategy') || 'samesign'; // Should not write on raw data, because stack series model list changes - // depending on legend selection. - - targetData.modify(dims, function (v0, v1, dataIndex) { - var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); // Consider `connectNulls` of line area, if value is NaN, stackedOver - // should also be NaN, to draw a appropriate belt area. - - if (isNaN(sum)) { - return resultNaN; - } - - var byValue; - var stackedDataRawIndex; - - if (isStackedByIndex) { - stackedDataRawIndex = targetData.getRawIndex(dataIndex); - } else { - byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex); - } // If stackOver is NaN, chart view will render point on value start. - - - var stackedOver = NaN; - - for (var j = idxInStack - 1; j >= 0; j--) { - var stackInfo = stackInfoList[j]; // Has been optimized by inverted indices on `stackedByDimension`. - - if (!isStackedByIndex) { - stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue); - } - - if (stackedDataRawIndex >= 0) { - var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); // Considering positive stack, negative stack and empty data - - if (stackStrategy === 'all' // single stack group - || stackStrategy === 'positive' && val > 0 || stackStrategy === 'negative' && val < 0 || stackStrategy === 'samesign' && sum >= 0 && val > 0 // All positive stack - || stackStrategy === 'samesign' && sum <= 0 && val < 0 // All negative stack - ) { - // The sum has to be very small to be affected by the - // floating arithmetic problem. An incorrect result will probably - // cause axis min/max to be filtered incorrectly. - sum = addSafe(sum, val); - stackedOver = val; - break; - } - } - } - - resultVal[0] = sum; - resultVal[1] = stackedOver; - return resultVal; - }); - }); - } // @inner - - - var SourceImpl = - /** @class */ - function () { - function SourceImpl(fields) { - this.data = fields.data || (fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []); - this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; // Visit config - - this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN; - this.startIndex = fields.startIndex || 0; - this.dimensionsDetectedCount = fields.dimensionsDetectedCount; - this.metaRawOption = fields.metaRawOption; - var dimensionsDefine = this.dimensionsDefine = fields.dimensionsDefine; - - if (dimensionsDefine) { - for (var i = 0; i < dimensionsDefine.length; i++) { - var dim = dimensionsDefine[i]; - - if (dim.type == null) { - if (guessOrdinal(this, i) === BE_ORDINAL.Must) { - dim.type = 'ordinal'; - } - } - } - } - } - - return SourceImpl; - }(); - - function isSourceInstance(val) { - return val instanceof SourceImpl; - } - /** - * Create a source from option. - * NOTE: Created source is immutable. Don't change any properties in it. - */ - - - function createSource(sourceData, thisMetaRawOption, // can be null. If not provided, auto detect it from `sourceData`. - sourceFormat) { - sourceFormat = sourceFormat || detectSourceFormat(sourceData); - var seriesLayoutBy = thisMetaRawOption.seriesLayoutBy; - var determined = determineSourceDimensions(sourceData, sourceFormat, seriesLayoutBy, thisMetaRawOption.sourceHeader, thisMetaRawOption.dimensions); - var source = new SourceImpl({ - data: sourceData, - sourceFormat: sourceFormat, - seriesLayoutBy: seriesLayoutBy, - dimensionsDefine: determined.dimensionsDefine, - startIndex: determined.startIndex, - dimensionsDetectedCount: determined.dimensionsDetectedCount, - metaRawOption: clone$3(thisMetaRawOption) - }); - return source; - } - /** - * Wrap original series data for some compatibility cases. - */ - - - function createSourceFromSeriesDataOption(data) { - return new SourceImpl({ - data: data, - sourceFormat: isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL - }); - } - /** - * Clone source but excludes source data. - */ - - - function cloneSourceShallow(source) { - return new SourceImpl({ - data: source.data, - sourceFormat: source.sourceFormat, - seriesLayoutBy: source.seriesLayoutBy, - dimensionsDefine: clone$3(source.dimensionsDefine), - startIndex: source.startIndex, - dimensionsDetectedCount: source.dimensionsDetectedCount - }); - } - /** - * Note: An empty array will be detected as `SOURCE_FORMAT_ARRAY_ROWS`. - */ - - - function detectSourceFormat(data) { - var sourceFormat = SOURCE_FORMAT_UNKNOWN; - - if (isTypedArray(data)) { - sourceFormat = SOURCE_FORMAT_TYPED_ARRAY; - } else if (isArray(data)) { - // FIXME Whether tolerate null in top level array? - if (data.length === 0) { - sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; - } - - for (var i = 0, len = data.length; i < len; i++) { - var item = data[i]; - - if (item == null) { - continue; - } else if (isArray(item) || isTypedArray(item)) { - sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; - break; - } else if (isObject$2(item)) { - sourceFormat = SOURCE_FORMAT_OBJECT_ROWS; - break; - } - } - } else if (isObject$2(data)) { - for (var key in data) { - if (hasOwn(data, key) && isArrayLike(data[key])) { - sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS; - break; - } - } - } - - return sourceFormat; - } - /** - * Determine the source definitions from data standalone dimensions definitions - * are not specified. - */ - - - function determineSourceDimensions(data, sourceFormat, seriesLayoutBy, sourceHeader, // standalone raw dimensions definition, like: - // { - // dimensions: ['aa', 'bb', { name: 'cc', type: 'time' }] - // } - // in `dataset` or `series` - dimensionsDefine) { - var dimensionsDetectedCount; - var startIndex; // PENDING: Could data be null/undefined here? - // currently, if `dataset.source` not specified, error thrown. - // if `series.data` not specified, nothing rendered without error thrown. - // Should test these cases. - - if (!data) { - return { - dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), - startIndex: startIndex, - dimensionsDetectedCount: dimensionsDetectedCount - }; - } - - if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { - var dataArrayRows = data; // Rule: Most of the first line are string: it is header. - // Caution: consider a line with 5 string and 1 number, - // it still can not be sure it is a head, because the - // 5 string may be 5 values of category columns. - - if (sourceHeader === 'auto' || sourceHeader == null) { - arrayRowsTravelFirst(function (val) { - // '-' is regarded as null/undefined. - if (val != null && val !== '-') { - if (isString(val)) { - startIndex == null && (startIndex = 1); - } else { - startIndex = 0; - } - } // 10 is an experience number, avoid long loop. - - }, seriesLayoutBy, dataArrayRows, 10); - } else { - startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0; - } - - if (!dimensionsDefine && startIndex === 1) { - dimensionsDefine = []; - arrayRowsTravelFirst(function (val, index) { - dimensionsDefine[index] = val != null ? val + '' : ''; - }, seriesLayoutBy, dataArrayRows, Infinity); - } - - dimensionsDetectedCount = dimensionsDefine ? dimensionsDefine.length : seriesLayoutBy === SERIES_LAYOUT_BY_ROW ? dataArrayRows.length : dataArrayRows[0] ? dataArrayRows[0].length : null; - } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { - if (!dimensionsDefine) { - dimensionsDefine = objectRowsCollectDimensions(data); - } - } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { - if (!dimensionsDefine) { - dimensionsDefine = []; - each$4(data, function (colArr, key) { - dimensionsDefine.push(key); - }); - } - } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { - var value0 = getDataItemValue(data[0]); - dimensionsDetectedCount = isArray(value0) && value0.length || 1; - } else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { - { - assert(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.'); - } - } - - return { - startIndex: startIndex, - dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), - dimensionsDetectedCount: dimensionsDetectedCount - }; - } - - function objectRowsCollectDimensions(data) { - var firstIndex = 0; - var obj; - - while (firstIndex < data.length && !(obj = data[firstIndex++])) {} // jshint ignore: line - - - if (obj) { - return keys(obj); - } - } // Consider dimensions defined like ['A', 'price', 'B', 'price', 'C', 'price'], - // which is reasonable. But dimension name is duplicated. - // Returns undefined or an array contains only object without null/undefined or string. - - - function normalizeDimensionsOption(dimensionsDefine) { - if (!dimensionsDefine) { - // The meaning of null/undefined is different from empty array. - return; - } - - var nameMap = createHashMap(); - return map$1(dimensionsDefine, function (rawItem, index) { - rawItem = isObject$2(rawItem) ? rawItem : { - name: rawItem - }; // Other fields will be discarded. - - var item = { - name: rawItem.name, - displayName: rawItem.displayName, - type: rawItem.type - }; // User can set null in dimensions. - // We don't auto specify name, otherwise a given name may - // cause it to be referred unexpectedly. - - if (item.name == null) { - return item; - } // Also consider number form like 2012. - - - item.name += ''; // User may also specify displayName. - // displayName will always exists except user not - // specified or dim name is not specified or detected. - // (A auto generated dim name will not be used as - // displayName). - - if (item.displayName == null) { - item.displayName = item.name; - } - - var exist = nameMap.get(item.name); - - if (!exist) { - nameMap.set(item.name, { - count: 1 - }); - } else { - item.name += '-' + exist.count++; - } - - return item; - }); - } - - function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) { - if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { - for (var i = 0; i < data.length && i < maxLoop; i++) { - cb(data[i] ? data[i][0] : null, i); - } - } else { - var value0 = data[0] || []; - - for (var i = 0; i < value0.length && i < maxLoop; i++) { - cb(value0[i], i); - } - } - } - - function shouldRetrieveDataByName(source) { - var sourceFormat = source.sourceFormat; - return sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS; - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - var _a, _b, _c; - - var providerMethods; - var mountMethods; - /** - * If normal array used, mutable chunk size is supported. - * If typed array used, chunk size must be fixed. - */ - - var DefaultDataProvider = - /** @class */ - function () { - function DefaultDataProvider(sourceParam, dimSize) { - // let source: Source; - var source = !isSourceInstance(sourceParam) ? createSourceFromSeriesDataOption(sourceParam) : sourceParam; // declare source is Source; - - this._source = source; - var data = this._data = source.data; // Typed array. TODO IE10+? - - if (source.sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { - { - if (dimSize == null) { - throw new Error('Typed array data must specify dimension size'); - } - } - this._offset = 0; - this._dimSize = dimSize; - this._data = data; - } - - mountMethods(this, data, source); - } - - DefaultDataProvider.prototype.getSource = function () { - return this._source; - }; - - DefaultDataProvider.prototype.count = function () { - return 0; - }; - - DefaultDataProvider.prototype.getItem = function (idx, out) { - return; - }; - - DefaultDataProvider.prototype.appendData = function (newData) {}; - - DefaultDataProvider.prototype.clean = function () {}; - - DefaultDataProvider.protoInitialize = function () { - // PENDING: To avoid potential incompat (e.g., prototype - // is visited somewhere), still init them on prototype. - var proto = DefaultDataProvider.prototype; - proto.pure = false; - proto.persistent = true; - }(); - - DefaultDataProvider.internalField = function () { - var _a; - - mountMethods = function (provider, data, source) { - var sourceFormat = source.sourceFormat; - var seriesLayoutBy = source.seriesLayoutBy; - var startIndex = source.startIndex; - var dimsDef = source.dimensionsDefine; - var methods = providerMethods[getMethodMapKey(sourceFormat, seriesLayoutBy)]; - { - assert(methods, 'Invalide sourceFormat: ' + sourceFormat); - } - extend(provider, methods); - - if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { - provider.getItem = getItemForTypedArray; - provider.count = countForTypedArray; - provider.fillStorage = fillStorageForTypedArray; - } else { - var rawItemGetter = getRawSourceItemGetter(sourceFormat, seriesLayoutBy); - provider.getItem = bind$1(rawItemGetter, null, data, startIndex, dimsDef); - var rawCounter = getRawSourceDataCounter(sourceFormat, seriesLayoutBy); - provider.count = bind$1(rawCounter, null, data, startIndex, dimsDef); - } - }; - - var getItemForTypedArray = function (idx, out) { - idx = idx - this._offset; - out = out || []; - var data = this._data; - var dimSize = this._dimSize; - var offset = dimSize * idx; - - for (var i = 0; i < dimSize; i++) { - out[i] = data[offset + i]; - } - - return out; - }; - - var fillStorageForTypedArray = function (start, end, storage, extent) { - var data = this._data; - var dimSize = this._dimSize; - - for (var dim = 0; dim < dimSize; dim++) { - var dimExtent = extent[dim]; - var min = dimExtent[0] == null ? Infinity : dimExtent[0]; - var max = dimExtent[1] == null ? -Infinity : dimExtent[1]; - var count = end - start; - var arr = storage[dim]; - - for (var i = 0; i < count; i++) { - // appendData with TypedArray will always do replace in provider. - var val = data[i * dimSize + dim]; - arr[start + i] = val; - val < min && (min = val); - val > max && (max = val); - } - - dimExtent[0] = min; - dimExtent[1] = max; - } - }; - - var countForTypedArray = function () { - return this._data ? this._data.length / this._dimSize : 0; - }; - - providerMethods = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = { - pure: true, - appendData: appendDataSimply - }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = { - pure: true, - appendData: function () { - throw new Error('Do not support appendData when set seriesLayoutBy: "row".'); - } - }, _a[SOURCE_FORMAT_OBJECT_ROWS] = { - pure: true, - appendData: appendDataSimply - }, _a[SOURCE_FORMAT_KEYED_COLUMNS] = { - pure: true, - appendData: function (newData) { - var data = this._data; - each$4(newData, function (newCol, key) { - var oldCol = data[key] || (data[key] = []); - - for (var i = 0; i < (newCol || []).length; i++) { - oldCol.push(newCol[i]); - } - }); - } - }, _a[SOURCE_FORMAT_ORIGINAL] = { - appendData: appendDataSimply - }, _a[SOURCE_FORMAT_TYPED_ARRAY] = { - persistent: false, - pure: true, - appendData: function (newData) { - { - assert(isTypedArray(newData), 'Added data must be TypedArray if data in initialization is TypedArray'); - } - this._data = newData; - }, - // Clean self if data is already used. - clean: function () { - // PENDING - this._offset += this.count(); - this._data = null; - } - }, _a); - - function appendDataSimply(newData) { - for (var i = 0; i < newData.length; i++) { - this._data.push(newData[i]); - } - } - }(); - - return DefaultDataProvider; - }(); - - var getItemSimply = function (rawData, startIndex, dimsDef, idx) { - return rawData[idx]; - }; - - var rawSourceItemGetterMap = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef, idx) { - return rawData[idx + startIndex]; - }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef, idx, out) { - idx += startIndex; - var item = out || []; - var data = rawData; - - for (var i = 0; i < data.length; i++) { - var row = data[i]; - item[i] = row ? row[idx] : null; - } - - return item; - }, _a[SOURCE_FORMAT_OBJECT_ROWS] = getItemSimply, _a[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef, idx, out) { - var item = out || []; - - for (var i = 0; i < dimsDef.length; i++) { - var dimName = dimsDef[i].name; - { - if (dimName == null) { - throw new Error(); - } - } - var col = rawData[dimName]; - item[i] = col ? col[idx] : null; - } - - return item; - }, _a[SOURCE_FORMAT_ORIGINAL] = getItemSimply, _a); - - function getRawSourceItemGetter(sourceFormat, seriesLayoutBy) { - var method = rawSourceItemGetterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; - { - assert(method, 'Do not support get item on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); - } - return method; - } - - var countSimply = function (rawData, startIndex, dimsDef) { - return rawData.length; - }; - - var rawSourceDataCounterMap = (_b = {}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef) { - return Math.max(0, rawData.length - startIndex); - }, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef) { - var row = rawData[0]; - return row ? Math.max(0, row.length - startIndex) : 0; - }, _b[SOURCE_FORMAT_OBJECT_ROWS] = countSimply, _b[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef) { - var dimName = dimsDef[0].name; - { - if (dimName == null) { - throw new Error(); - } - } - var col = rawData[dimName]; - return col ? col.length : 0; - }, _b[SOURCE_FORMAT_ORIGINAL] = countSimply, _b); - - function getRawSourceDataCounter(sourceFormat, seriesLayoutBy) { - var method = rawSourceDataCounterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; - { - assert(method, 'Do not support count on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); - } - return method; - } - - var getRawValueSimply = function (dataItem, dimIndex, property) { - return dataItem[dimIndex]; - }; - - var rawSourceValueGetterMap = (_c = {}, _c[SOURCE_FORMAT_ARRAY_ROWS] = getRawValueSimply, _c[SOURCE_FORMAT_OBJECT_ROWS] = function (dataItem, dimIndex, property) { - return dataItem[property]; - }, _c[SOURCE_FORMAT_KEYED_COLUMNS] = getRawValueSimply, _c[SOURCE_FORMAT_ORIGINAL] = function (dataItem, dimIndex, property) { - // FIXME: In some case (markpoint in geo (geo-map.html)), - // dataItem is {coord: [...]} - var value = getDataItemValue(dataItem); - return !(value instanceof Array) ? value : value[dimIndex]; - }, _c[SOURCE_FORMAT_TYPED_ARRAY] = getRawValueSimply, _c); - - function getRawSourceValueGetter(sourceFormat) { - var method = rawSourceValueGetterMap[sourceFormat]; - { - assert(method, 'Do not support get value on "' + sourceFormat + '".'); - } - return method; - } - - function getMethodMapKey(sourceFormat, seriesLayoutBy) { - return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + seriesLayoutBy : sourceFormat; - } // ??? FIXME can these logic be more neat: getRawValue, getRawDataItem, - // Consider persistent. - // Caution: why use raw value to display on label or tooltip? - // A reason is to avoid format. For example time value we do not know - // how to format is expected. More over, if stack is used, calculated - // value may be 0.91000000001, which have brings trouble to display. - // TODO: consider how to treat null/undefined/NaN when display? - - - function retrieveRawValue(data, dataIndex, // If dimIndex is null/undefined, return OptionDataItem. - // Otherwise, return OptionDataValue. - dim) { - if (!data) { - return; - } // Consider data may be not persistent. - - - var dataItem = data.getRawDataItem(dataIndex); - - if (dataItem == null) { - return; - } - - var store = data.getStore(); - var sourceFormat = store.getSource().sourceFormat; - - if (dim != null) { - var dimIndex = data.getDimensionIndex(dim); - var property = store.getDimensionProperty(dimIndex); - return getRawSourceValueGetter(sourceFormat)(dataItem, dimIndex, property); - } else { - var result = dataItem; - - if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { - result = getDataItemValue(dataItem); - } - - return result; - } - } - - var DIMENSION_LABEL_REG = /\{@(.+?)\}/g; - - var DataFormatMixin = - /** @class */ - function () { - function DataFormatMixin() {} - /** - * Get params for formatter - */ - - - DataFormatMixin.prototype.getDataParams = function (dataIndex, dataType) { - var data = this.getData(dataType); - var rawValue = this.getRawValue(dataIndex, dataType); - var rawDataIndex = data.getRawIndex(dataIndex); - var name = data.getName(dataIndex); - var itemOpt = data.getRawDataItem(dataIndex); - var style = data.getItemVisual(dataIndex, 'style'); - var color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill']; - var borderColor = style && style.stroke; - var mainType = this.mainType; - var isSeries = mainType === 'series'; - var userOutput = data.userOutput && data.userOutput.get(); - return { - componentType: mainType, - componentSubType: this.subType, - componentIndex: this.componentIndex, - seriesType: isSeries ? this.subType : null, - seriesIndex: this.seriesIndex, - seriesId: isSeries ? this.id : null, - seriesName: isSeries ? this.name : null, - name: name, - dataIndex: rawDataIndex, - data: itemOpt, - dataType: dataType, - value: rawValue, - color: color, - borderColor: borderColor, - dimensionNames: userOutput ? userOutput.fullDimensions : null, - encode: userOutput ? userOutput.encode : null, - // Param name list for mapping `a`, `b`, `c`, `d`, `e` - $vars: ['seriesName', 'name', 'value'] - }; - }; - /** - * Format label - * @param dataIndex - * @param status 'normal' by default - * @param dataType - * @param labelDimIndex Only used in some chart that - * use formatter in different dimensions, like radar. - * @param formatter Formatter given outside. - * @return return null/undefined if no formatter - */ - - - DataFormatMixin.prototype.getFormattedLabel = function (dataIndex, status, dataType, labelDimIndex, formatter, extendParams) { - status = status || 'normal'; - var data = this.getData(dataType); - var params = this.getDataParams(dataIndex, dataType); - - if (extendParams) { - params.value = extendParams.interpolatedValue; - } - - if (labelDimIndex != null && isArray(params.value)) { - params.value = params.value[labelDimIndex]; - } - - if (!formatter) { - var itemModel = data.getItemModel(dataIndex); // @ts-ignore - - formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : [status, 'label', 'formatter']); - } - - if (isFunction(formatter)) { - params.status = status; - params.dimensionIndex = labelDimIndex; - return formatter(params); - } else if (isString(formatter)) { - var str = formatTpl(formatter, params); // Support 'aaa{@[3]}bbb{@product}ccc'. - // Do not support '}' in dim name util have to. - - return str.replace(DIMENSION_LABEL_REG, function (origin, dimStr) { - var len = dimStr.length; - var dimLoose = dimStr; - - if (dimLoose.charAt(0) === '[' && dimLoose.charAt(len - 1) === ']') { - dimLoose = +dimLoose.slice(1, len - 1); // Also support: '[]' => 0 - - { - if (isNaN(dimLoose)) { - error("Invalide label formatter: @" + dimStr + ", only support @[0], @[1], @[2], ..."); - } - } - } - - var val = retrieveRawValue(data, dataIndex, dimLoose); - - if (extendParams && isArray(extendParams.interpolatedValue)) { - var dimIndex = data.getDimensionIndex(dimLoose); - - if (dimIndex >= 0) { - val = extendParams.interpolatedValue[dimIndex]; - } - } - - return val != null ? val + '' : ''; - }); - } - }; - /** - * Get raw value in option - */ - - - DataFormatMixin.prototype.getRawValue = function (idx, dataType) { - return retrieveRawValue(this.getData(dataType), idx); - }; - /** - * Should be implemented. - * @param {number} dataIndex - * @param {boolean} [multipleSeries=false] - * @param {string} [dataType] - */ - - - DataFormatMixin.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { - // Empty function - return; - }; - - return DataFormatMixin; - }(); // PENDING: previously we accept this type when calling `formatTooltip`, - // but guess little chance has been used outside. Do we need to backward - // compat it? - // type TooltipFormatResultLegacyObject = { - // // `html` means the markup language text, either in 'html' or 'richText'. - // // The name `html` is not appropriate because in 'richText' it is not a HTML - // // string. But still support it for backward compatibility. - // html: string; - // markers: Dictionary; - // }; - - /** - * For backward compat, normalize the return from `formatTooltip`. - */ - - - function normalizeTooltipFormatResult(result) { - var markupText; // let markers: Dictionary; - - var markupFragment; - - if (isObject$2(result)) { - if (result.type) { - markupFragment = result; - } else { - { - console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result)); - } - } // else { - // markupText = (result as TooltipFormatResultLegacyObject).html; - // markers = (result as TooltipFormatResultLegacyObject).markers; - // if (markersExisting) { - // markers = zrUtil.merge(markersExisting, markers); - // } - // } - - } else { - markupText = result; - } - - return { - text: markupText, - // markers: markers || markersExisting, - frag: markupFragment - }; - } - /** - * @param {Object} define - * @return See the return of `createTask`. - */ - - - function createTask(define) { - return new Task(define); - } - - var Task = - /** @class */ - function () { - function Task(define) { - define = define || {}; - this._reset = define.reset; - this._plan = define.plan; - this._count = define.count; - this._onDirty = define.onDirty; - this._dirty = true; - } - /** - * @param step Specified step. - * @param skip Skip customer perform call. - * @param modBy Sampling window size. - * @param modDataCount Sampling count. - * @return whether unfinished. - */ - - - Task.prototype.perform = function (performArgs) { - var upTask = this._upstream; - var skip = performArgs && performArgs.skip; // TODO some refactor. - // Pull data. Must pull data each time, because context.data - // may be updated by Series.setData. - - if (this._dirty && upTask) { - var context = this.context; - context.data = context.outputData = upTask.context.outputData; - } - - if (this.__pipeline) { - this.__pipeline.currentTask = this; - } - - var planResult; - - if (this._plan && !skip) { - planResult = this._plan(this.context); - } // Support sharding by mod, which changes the render sequence and makes the rendered graphic - // elements uniformed distributed when progress, especially when moving or zooming. - - - var lastModBy = normalizeModBy(this._modBy); - var lastModDataCount = this._modDataCount || 0; - var modBy = normalizeModBy(performArgs && performArgs.modBy); - var modDataCount = performArgs && performArgs.modDataCount || 0; - - if (lastModBy !== modBy || lastModDataCount !== modDataCount) { - planResult = 'reset'; - } - - function normalizeModBy(val) { - !(val >= 1) && (val = 1); // jshint ignore:line - - return val; - } - - var forceFirstProgress; - - if (this._dirty || planResult === 'reset') { - this._dirty = false; - forceFirstProgress = this._doReset(skip); - } - - this._modBy = modBy; - this._modDataCount = modDataCount; - var step = performArgs && performArgs.step; - - if (upTask) { - { - assert(upTask._outputDueEnd != null); - } - this._dueEnd = upTask._outputDueEnd; - } // DataTask or overallTask - else { - { - assert(!this._progress || this._count); - } - this._dueEnd = this._count ? this._count(this.context) : Infinity; - } // Note: Stubs, that its host overall task let it has progress, has progress. - // If no progress, pass index from upstream to downstream each time plan called. - - - if (this._progress) { - var start = this._dueIndex; - var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd); - - if (!skip && (forceFirstProgress || start < end)) { - var progress = this._progress; - - if (isArray(progress)) { - for (var i = 0; i < progress.length; i++) { - this._doProgress(progress[i], start, end, modBy, modDataCount); - } - } else { - this._doProgress(progress, start, end, modBy, modDataCount); - } - } - - this._dueIndex = end; // If no `outputDueEnd`, assume that output data and - // input data is the same, so use `dueIndex` as `outputDueEnd`. - - var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end; - { - // ??? Can not rollback. - assert(outputDueEnd >= this._outputDueEnd); - } - this._outputDueEnd = outputDueEnd; - } else { - // (1) Some overall task has no progress. - // (2) Stubs, that its host overall task do not let it has progress, has no progress. - // This should always be performed so it can be passed to downstream. - this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd; - } - - return this.unfinished(); - }; - - Task.prototype.dirty = function () { - this._dirty = true; - this._onDirty && this._onDirty(this.context); - }; - - Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) { - iterator.reset(start, end, modBy, modDataCount); - this._callingProgress = progress; - - this._callingProgress({ - start: start, - end: end, - count: end - start, - next: iterator.next - }, this.context); - }; - - Task.prototype._doReset = function (skip) { - this._dueIndex = this._outputDueEnd = this._dueEnd = 0; - this._settedOutputEnd = null; - var progress; - var forceFirstProgress; - - if (!skip && this._reset) { - progress = this._reset(this.context); - - if (progress && progress.progress) { - forceFirstProgress = progress.forceFirstProgress; - progress = progress.progress; - } // To simplify no progress checking, array must has item. - - - if (isArray(progress) && !progress.length) { - progress = null; - } - } - - this._progress = progress; - this._modBy = this._modDataCount = null; - var downstream = this._downstream; - downstream && downstream.dirty(); - return forceFirstProgress; - }; - - Task.prototype.unfinished = function () { - return this._progress && this._dueIndex < this._dueEnd; - }; - /** - * @param downTask The downstream task. - * @return The downstream task. - */ - - - Task.prototype.pipe = function (downTask) { - { - assert(downTask && !downTask._disposed && downTask !== this); - } // If already downstream, do not dirty downTask. - - if (this._downstream !== downTask || this._dirty) { - this._downstream = downTask; - downTask._upstream = this; - downTask.dirty(); - } - }; - - Task.prototype.dispose = function () { - if (this._disposed) { - return; - } - - this._upstream && (this._upstream._downstream = null); - this._downstream && (this._downstream._upstream = null); - this._dirty = false; - this._disposed = true; - }; - - Task.prototype.getUpstream = function () { - return this._upstream; - }; - - Task.prototype.getDownstream = function () { - return this._downstream; - }; - - Task.prototype.setOutputEnd = function (end) { - // This only happens in dataTask, dataZoom, map, currently. - // where dataZoom do not set end each time, but only set - // when reset. So we should record the set end, in case - // that the stub of dataZoom perform again and earse the - // set end by upstream. - this._outputDueEnd = this._settedOutputEnd = end; - }; - - return Task; - }(); - - var iterator = function () { - var end; - var current; - var modBy; - var modDataCount; - var winCount; - var it = { - reset: function (s, e, sStep, sCount) { - current = s; - end = e; - modBy = sStep; - modDataCount = sCount; - winCount = Math.ceil(modDataCount / modBy); - it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext; - } - }; - return it; - - function sequentialNext() { - return current < end ? current++ : null; - } - - function modNext() { - var dataIndex = current % winCount * modBy + Math.ceil(current / winCount); - var result = current >= end ? null : dataIndex < modDataCount ? dataIndex // If modDataCount is smaller than data.count() (consider `appendData` case), - // Use normal linear rendering mode. - : current; - current++; - return result; - } - }(); // ----------------------------------------------------------------------------- - // For stream debug (Should be commented out after used!) - // @usage: printTask(this, 'begin'); - // @usage: printTask(this, null, {someExtraProp}); - // @usage: Use `__idxInPipeline` as conditional breakpiont. - // - // window.printTask = function (task: any, prefix: string, extra: { [key: string]: unknown }): void { - // window.ecTaskUID == null && (window.ecTaskUID = 0); - // task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`); - // task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`); - // let props = []; - // if (task.__pipeline) { - // let val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`; - // props.push({text: '__idxInPipeline/total', value: val}); - // } else { - // let stubCount = 0; - // task.agentStubMap.each(() => stubCount++); - // props.push({text: 'idx', value: `overall (stubs: ${stubCount})`}); - // } - // props.push({text: 'uid', value: task.uidDebug}); - // if (task.__pipeline) { - // props.push({text: 'pipelineId', value: task.__pipeline.id}); - // task.agent && props.push( - // {text: 'stubFor', value: task.agent.uidDebug} - // ); - // } - // props.push( - // {text: 'dirty', value: task._dirty}, - // {text: 'dueIndex', value: task._dueIndex}, - // {text: 'dueEnd', value: task._dueEnd}, - // {text: 'outputDueEnd', value: task._outputDueEnd} - // ); - // if (extra) { - // Object.keys(extra).forEach(key => { - // props.push({text: key, value: extra[key]}); - // }); - // } - // let args = ['color: blue']; - // let msg = `%c[${prefix || 'T'}] %c` + props.map(item => ( - // args.push('color: green', 'color: red'), - // `${item.text}: %c${item.value}` - // )).join('%c, '); - // console.log.apply(console, [msg].concat(args)); - // // console.log(this); - // }; - // window.printPipeline = function (task: any, prefix: string) { - // const pipeline = task.__pipeline; - // let currTask = pipeline.head; - // while (currTask) { - // window.printTask(currTask, prefix); - // currTask = currTask._downstream; - // } - // }; - // window.showChain = function (chainHeadTask) { - // var chain = []; - // var task = chainHeadTask; - // while (task) { - // chain.push({ - // task: task, - // up: task._upstream, - // down: task._downstream, - // idxInPipeline: task.__idxInPipeline - // }); - // task = task._downstream; - // } - // return chain; - // }; - // window.findTaskInChain = function (task, chainHeadTask) { - // let chain = window.showChain(chainHeadTask); - // let result = []; - // for (let i = 0; i < chain.length; i++) { - // let chainItem = chain[i]; - // if (chainItem.task === task) { - // result.push(i); - // } - // } - // return result; - // }; - // window.printChainAEachInChainB = function (chainHeadTaskA, chainHeadTaskB) { - // let chainA = window.showChain(chainHeadTaskA); - // for (let i = 0; i < chainA.length; i++) { - // console.log('chainAIdx:', i, 'inChainB:', window.findTaskInChain(chainA[i].task, chainHeadTaskB)); - // } - // }; - - /** - * Convert raw the value in to inner value in List. - * - * [Performance sensitive] - * - * [Caution]: this is the key logic of user value parser. - * For backward compatibility, do not modify it until you have to! - */ - - - function parseDataValue(value, // For high performance, do not omit the second param. - opt) { - // Performance sensitive. - var dimType = opt && opt.type; - - if (dimType === 'ordinal') { - // If given value is a category string - return value; - } - - if (dimType === 'time' // spead up when using timestamp - && !isNumber(value) && value != null && value !== '-') { - value = +parseDate(value); - } // dimType defaults 'number'. - // If dimType is not ordinal and value is null or undefined or NaN or '-', - // parse to NaN. - // number-like string (like ' 123 ') can be converted to a number. - // where null/undefined or other string will be converted to NaN. - - - return value == null || value === '' ? NaN // If string (like '-'), using '+' parse to NaN - // If object, also parse to NaN - : +value; - } - - var valueParserMap = createHashMap({ - 'number': function (val) { - // Do not use `numericToNumber` here. We have `numericToNumber` by default. - // Here the number parser can have loose rule: - // enable to cut suffix: "120px" => 120, "14%" => 14. - return parseFloat(val); - }, - 'time': function (val) { - // return timestamp. - return +parseDate(val); - }, - 'trim': function (val) { - return isString(val) ? trim(val) : val; - } - }); - - function getRawValueParser(type) { - return valueParserMap.get(type); - } - - var ORDER_COMPARISON_OP_MAP = { - lt: function (lval, rval) { - return lval < rval; - }, - lte: function (lval, rval) { - return lval <= rval; - }, - gt: function (lval, rval) { - return lval > rval; - }, - gte: function (lval, rval) { - return lval >= rval; - } - }; - - var FilterOrderComparator = - /** @class */ - function () { - function FilterOrderComparator(op, rval) { - if (!isNumber(rval)) { - var errMsg = ''; - { - errMsg = 'rvalue of "<", ">", "<=", ">=" can only be number in filter.'; - } - throwError(errMsg); - } - - this._opFn = ORDER_COMPARISON_OP_MAP[op]; - this._rvalFloat = numericToNumber(rval); - } // Performance sensitive. - - - FilterOrderComparator.prototype.evaluate = function (lval) { - // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat. - return isNumber(lval) ? this._opFn(lval, this._rvalFloat) : this._opFn(numericToNumber(lval), this._rvalFloat); - }; - - return FilterOrderComparator; - }(); - - var SortOrderComparator = - /** @class */ - function () { - /** - * @param order by default: 'asc' - * @param incomparable by default: Always on the tail. - * That is, if 'asc' => 'max', if 'desc' => 'min' - * See the definition of "incomparable" in [SORT_COMPARISON_RULE]. - */ - function SortOrderComparator(order, incomparable) { - var isDesc = order === 'desc'; - this._resultLT = isDesc ? 1 : -1; - - if (incomparable == null) { - incomparable = isDesc ? 'min' : 'max'; - } - - this._incomparable = incomparable === 'min' ? -Infinity : Infinity; - } // See [SORT_COMPARISON_RULE]. - // Performance sensitive. - - - SortOrderComparator.prototype.evaluate = function (lval, rval) { - // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat. - var lvalFloat = isNumber(lval) ? lval : numericToNumber(lval); - var rvalFloat = isNumber(rval) ? rval : numericToNumber(rval); - var lvalNotNumeric = isNaN(lvalFloat); - var rvalNotNumeric = isNaN(rvalFloat); - - if (lvalNotNumeric) { - lvalFloat = this._incomparable; - } - - if (rvalNotNumeric) { - rvalFloat = this._incomparable; - } - - if (lvalNotNumeric && rvalNotNumeric) { - var lvalIsStr = isString(lval); - var rvalIsStr = isString(rval); - - if (lvalIsStr) { - lvalFloat = rvalIsStr ? lval : 0; - } - - if (rvalIsStr) { - rvalFloat = lvalIsStr ? rval : 0; - } - } - - return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0; - }; - - return SortOrderComparator; - }(); - - var FilterEqualityComparator = - /** @class */ - function () { - function FilterEqualityComparator(isEq, rval) { - this._rval = rval; - this._isEQ = isEq; - this._rvalTypeof = typeof rval; - this._rvalFloat = numericToNumber(rval); - } // Performance sensitive. - - - FilterEqualityComparator.prototype.evaluate = function (lval) { - var eqResult = lval === this._rval; - - if (!eqResult) { - var lvalTypeof = typeof lval; - - if (lvalTypeof !== this._rvalTypeof && (lvalTypeof === 'number' || this._rvalTypeof === 'number')) { - eqResult = numericToNumber(lval) === this._rvalFloat; - } - } - - return this._isEQ ? eqResult : !eqResult; - }; - - return FilterEqualityComparator; - }(); - /** - * [FILTER_COMPARISON_RULE] - * `lt`|`lte`|`gt`|`gte`: - * + rval must be a number. And lval will be converted to number (`numericToNumber`) to compare. - * `eq`: - * + If same type, compare with `===`. - * + If there is one number, convert to number (`numericToNumber`) to compare. - * + Else return `false`. - * `ne`: - * + Not `eq`. - * - * - * [SORT_COMPARISON_RULE] - * All the values are grouped into three categories: - * + "numeric" (number and numeric string) - * + "non-numeric-string" (string that excluding numeric string) - * + "others" - * "numeric" vs "numeric": values are ordered by number order. - * "non-numeric-string" vs "non-numeric-string": values are ordered by ES spec (#sec-abstract-relational-comparison). - * "others" vs "others": do not change order (always return 0). - * "numeric" vs "non-numeric-string": "non-numeric-string" is treated as "incomparable". - * "number" vs "others": "others" is treated as "incomparable". - * "non-numeric-string" vs "others": "others" is treated as "incomparable". - * "incomparable" will be seen as -Infinity or Infinity (depends on the settings). - * MEMO: - * Non-numeric string sort makes sense when we need to put the items with the same tag together. - * But if we support string sort, we still need to avoid the misleading like `'2' > '12'`, - * So we treat "numeric-string" sorted by number order rather than string comparison. - * - * - * [CHECK_LIST_OF_THE_RULE_DESIGN] - * + Do not support string comparison until required. And also need to - * avoid the misleading of "2" > "12". - * + Should avoid the misleading case: - * `" 22 " gte "22"` is `true` but `" 22 " eq "22"` is `false`. - * + JS bad case should be avoided: null <= 0, [] <= 0, ' ' <= 0, ... - * + Only "numeric" can be converted to comparable number, otherwise converted to NaN. - * See `util/number.ts#numericToNumber`. - * - * @return If `op` is not `RelationalOperator`, return null; - */ - - - function createFilterComparator(op, rval) { - return op === 'eq' || op === 'ne' ? new FilterEqualityComparator(op === 'eq', rval) : hasOwn(ORDER_COMPARISON_OP_MAP, op) ? new FilterOrderComparator(op, rval) : null; - } - /** - * TODO: disable writable. - * This structure will be exposed to users. - */ - - - var ExternalSource = - /** @class */ - function () { - function ExternalSource() {} - - ExternalSource.prototype.getRawData = function () { - // Only built-in transform available. - throw new Error('not supported'); - }; - - ExternalSource.prototype.getRawDataItem = function (dataIndex) { - // Only built-in transform available. - throw new Error('not supported'); - }; - - ExternalSource.prototype.cloneRawData = function () { - return; - }; - /** - * @return If dimension not found, return null/undefined. - */ - - - ExternalSource.prototype.getDimensionInfo = function (dim) { - return; - }; - /** - * dimensions defined if and only if either: - * (a) dataset.dimensions are declared. - * (b) dataset data include dimensions definitions in data (detected or via specified `sourceHeader`). - * If dimensions are defined, `dimensionInfoAll` is corresponding to - * the defined dimensions. - * Otherwise, `dimensionInfoAll` is determined by data columns. - * @return Always return an array (even empty array). - */ - - - ExternalSource.prototype.cloneAllDimensionInfo = function () { - return; - }; - - ExternalSource.prototype.count = function () { - return; - }; - /** - * Only support by dimension index. - * No need to support by dimension name in transform function, - * because transform function is not case-specific, no need to use name literally. - */ - - - ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) { - return; - }; - - ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) { - return; - }; - - ExternalSource.prototype.convertValue = function (rawVal, dimInfo) { - return parseDataValue(rawVal, dimInfo); - }; - - return ExternalSource; - }(); - - function createExternalSource(internalSource, externalTransform) { - var extSource = new ExternalSource(); - var data = internalSource.data; - var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat; - var sourceHeaderCount = internalSource.startIndex; - var errMsg = ''; - - if (internalSource.seriesLayoutBy !== SERIES_LAYOUT_BY_COLUMN) { - // For the logic simplicity in transformer, only 'culumn' is - // supported in data transform. Otherwise, the `dimensionsDefine` - // might be detected by 'row', which probably confuses users. - { - errMsg = '`seriesLayoutBy` of upstream dataset can only be "column" in data transform.'; - } - throwError(errMsg); - } // [MEMO] - // Create a new dimensions structure for exposing. - // Do not expose all dimension info to users directly. - // Because the dimension is probably auto detected from data and not might reliable. - // Should not lead the transformers to think that is reliable and return it. - // See [DIMENSION_INHERIT_RULE] in `sourceManager.ts`. - - - var dimensions = []; - var dimsByName = {}; - var dimsDef = internalSource.dimensionsDefine; - - if (dimsDef) { - each$4(dimsDef, function (dimDef, idx) { - var name = dimDef.name; - var dimDefExt = { - index: idx, - name: name, - displayName: dimDef.displayName - }; - dimensions.push(dimDefExt); // Users probably do not specify dimension name. For simplicity, data transform - // does not generate dimension name. - - if (name != null) { - // Dimension name should not be duplicated. - // For simplicity, data transform forbids name duplication, do not generate - // new name like module `completeDimensions.ts` did, but just tell users. - var errMsg_1 = ''; - - if (hasOwn(dimsByName, name)) { - { - errMsg_1 = 'dimension name "' + name + '" duplicated.'; - } - throwError(errMsg_1); - } - - dimsByName[name] = dimDefExt; - } - }); - } // If dimension definitions are not defined and can not be detected. - // e.g., pure data `[[11, 22], ...]`. - else { - for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) { - // Do not generete name or anything others. The consequence process in - // `transform` or `series` probably have there own name generation strategry. - dimensions.push({ - index: i - }); - } - } // Implement public methods: - - - var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); - - if (externalTransform.__isBuiltIn) { - extSource.getRawDataItem = function (dataIndex) { - return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); - }; - - extSource.getRawData = bind$1(getRawData, null, internalSource); - } - - extSource.cloneRawData = bind$1(cloneRawData, null, internalSource); - var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); - extSource.count = bind$1(rawCounter, null, data, sourceHeaderCount, dimensions); - var rawValueGetter = getRawSourceValueGetter(sourceFormat); - - extSource.retrieveValue = function (dataIndex, dimIndex) { - var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); - return retrieveValueFromItem(rawItem, dimIndex); - }; - - var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) { - if (dataItem == null) { - return; - } - - var dimDef = dimensions[dimIndex]; // When `dimIndex` is `null`, `rawValueGetter` return the whole item. - - if (dimDef) { - return rawValueGetter(dataItem, dimIndex, dimDef.name); - } - }; - - extSource.getDimensionInfo = bind$1(getDimensionInfo, null, dimensions, dimsByName); - extSource.cloneAllDimensionInfo = bind$1(cloneAllDimensionInfo, null, dimensions); - return extSource; - } - - function getRawData(upstream) { - var sourceFormat = upstream.sourceFormat; - - if (!isSupportedSourceFormat(sourceFormat)) { - var errMsg = ''; - { - errMsg = '`getRawData` is not supported in source format ' + sourceFormat; - } - throwError(errMsg); - } - - return upstream.data; - } - - function cloneRawData(upstream) { - var sourceFormat = upstream.sourceFormat; - var data = upstream.data; - - if (!isSupportedSourceFormat(sourceFormat)) { - var errMsg = ''; - { - errMsg = '`cloneRawData` is not supported in source format ' + sourceFormat; - } - throwError(errMsg); - } - - if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { - var result = []; - - for (var i = 0, len = data.length; i < len; i++) { - // Not strictly clone for performance - result.push(data[i].slice()); - } - - return result; - } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { - var result = []; - - for (var i = 0, len = data.length; i < len; i++) { - // Not strictly clone for performance - result.push(extend({}, data[i])); - } - - return result; - } - } - - function getDimensionInfo(dimensions, dimsByName, dim) { - if (dim == null) { - return; - } // Keep the same logic as `List::getDimension` did. - - - if (isNumber(dim) // If being a number-like string but not being defined a dimension name. - || !isNaN(dim) && !hasOwn(dimsByName, dim)) { - return dimensions[dim]; - } else if (hasOwn(dimsByName, dim)) { - return dimsByName[dim]; - } - } - - function cloneAllDimensionInfo(dimensions) { - return clone$3(dimensions); - } - - var externalTransformMap = createHashMap(); - - function registerExternalTransform(externalTransform) { - externalTransform = clone$3(externalTransform); - var type = externalTransform.type; - var errMsg = ''; - - if (!type) { - { - errMsg = 'Must have a `type` when `registerTransform`.'; - } - throwError(errMsg); - } - - var typeParsed = type.split(':'); - - if (typeParsed.length !== 2) { - { - errMsg = 'Name must include namespace like "ns:regression".'; - } - throwError(errMsg); - } // Namespace 'echarts:xxx' is official namespace, where the transforms should - // be called directly via 'xxx' rather than 'echarts:xxx'. - - - var isBuiltIn = false; - - if (typeParsed[0] === 'echarts') { - type = typeParsed[1]; - isBuiltIn = true; - } - - externalTransform.__isBuiltIn = isBuiltIn; - externalTransformMap.set(type, externalTransform); - } - - function applyDataTransform(rawTransOption, sourceList, infoForPrint) { - var pipedTransOption = normalizeToArray(rawTransOption); - var pipeLen = pipedTransOption.length; - var errMsg = ''; - - if (!pipeLen) { - { - errMsg = 'If `transform` declared, it should at least contain one transform.'; - } - throwError(errMsg); - } - - for (var i = 0, len = pipeLen; i < len; i++) { - var transOption = pipedTransOption[i]; - sourceList = applySingleDataTransform(transOption, sourceList, infoForPrint, pipeLen === 1 ? null : i); // piped transform only support single input, except the fist one. - // piped transform only support single output, except the last one. - - if (i !== len - 1) { - sourceList.length = Math.max(sourceList.length, 1); - } - } - - return sourceList; - } - - function applySingleDataTransform(transOption, upSourceList, infoForPrint, // If `pipeIndex` is null/undefined, no piped transform. - pipeIndex) { - var errMsg = ''; - - if (!upSourceList.length) { - { - errMsg = 'Must have at least one upstream dataset.'; - } - throwError(errMsg); - } - - if (!isObject$2(transOption)) { - { - errMsg = 'transform declaration must be an object rather than ' + typeof transOption + '.'; - } - throwError(errMsg); - } - - var transType = transOption.type; - var externalTransform = externalTransformMap.get(transType); - - if (!externalTransform) { - { - errMsg = 'Can not find transform on type "' + transType + '".'; - } - throwError(errMsg); - } // Prepare source - - - var extUpSourceList = map$1(upSourceList, function (upSource) { - return createExternalSource(upSource, externalTransform); - }); - var resultList = normalizeToArray(externalTransform.transform({ - upstream: extUpSourceList[0], - upstreamList: extUpSourceList, - config: clone$3(transOption.config) - })); - { - if (transOption.print) { - var printStrArr = map$1(resultList, function (extSource) { - var pipeIndexStr = pipeIndex != null ? ' === pipe index: ' + pipeIndex : ''; - return ['=== dataset index: ' + infoForPrint.datasetIndex + pipeIndexStr + ' ===', '- transform result data:', makePrintable(extSource.data), '- transform result dimensions:', makePrintable(extSource.dimensions)].join('\n'); - }).join('\n'); - log(printStrArr); - } - } - return map$1(resultList, function (result, resultIndex) { - var errMsg = ''; - - if (!isObject$2(result)) { - { - errMsg = 'A transform should not return some empty results.'; - } - throwError(errMsg); - } - - if (!result.data) { - { - errMsg = 'Transform result data should be not be null or undefined'; - } - throwError(errMsg); - } - - var sourceFormat = detectSourceFormat(result.data); - - if (!isSupportedSourceFormat(sourceFormat)) { - { - errMsg = 'Transform result data should be array rows or object rows.'; - } - throwError(errMsg); - } - - var resultMetaRawOption; - var firstUpSource = upSourceList[0]; - /** - * Intuitively, the end users known the content of the original `dataset.source`, - * calucating the transform result in mind. - * Suppose the original `dataset.source` is: - * ```js - * [ - * ['product', '2012', '2013', '2014', '2015'], - * ['AAA', 41.1, 30.4, 65.1, 53.3], - * ['BBB', 86.5, 92.1, 85.7, 83.1], - * ['CCC', 24.1, 67.2, 79.5, 86.4] - * ] - * ``` - * The dimension info have to be detected from the source data. - * Some of the transformers (like filter, sort) will follow the dimension info - * of upstream, while others use new dimensions (like aggregate). - * Transformer can output a field `dimensions` to define the its own output dimensions. - * We also allow transformers to ignore the output `dimensions` field, and - * inherit the upstream dimensions definition. It can reduce the burden of handling - * dimensions in transformers. - * - * See also [DIMENSION_INHERIT_RULE] in `sourceManager.ts`. - */ - - if (firstUpSource && resultIndex === 0 // If transformer returns `dimensions`, it means that the transformer has different - // dimensions definitions. We do not inherit anything from upstream. - && !result.dimensions) { - var startIndex = firstUpSource.startIndex; // We copy the header of upstream to the result, because: - // (1) The returned data always does not contain header line and can not be used - // as dimension-detection. In this case we can not use "detected dimensions" of - // upstream directly, because it might be detected based on different `seriesLayoutBy`. - // (2) We should support that the series read the upstream source in `seriesLayoutBy: 'row'`. - // So the original detected header should be add to the result, otherwise they can not be read. - - if (startIndex) { - result.data = firstUpSource.data.slice(0, startIndex).concat(result.data); - } - - resultMetaRawOption = { - seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, - sourceHeader: startIndex, - dimensions: firstUpSource.metaRawOption.dimensions - }; - } else { - resultMetaRawOption = { - seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, - sourceHeader: 0, - dimensions: result.dimensions - }; - } - - return createSource(result.data, resultMetaRawOption, null); - }); - } - - function isSupportedSourceFormat(sourceFormat) { - return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS; - } - - var UNDEFINED = 'undefined'; - /* global Float64Array, Int32Array, Uint32Array, Uint16Array */ - // Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is - // different from the Ctor of typed array. - - var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array; - var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array; - var CtorInt32Array$1 = typeof Int32Array === UNDEFINED ? Array : Int32Array; - var CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array; - /** - * Multi dimensional data store - */ - - var dataCtors = { - 'float': CtorFloat64Array, - 'int': CtorInt32Array$1, - // Ordinal data type can be string or int - 'ordinal': Array, - 'number': Array, - 'time': CtorFloat64Array - }; - var defaultDimValueGetters; - - function getIndicesCtor(rawCount) { - // The possible max value in this._indicies is always this._rawCount despite of filtering. - return rawCount > 65535 ? CtorUint32Array : CtorUint16Array; - } - - function getInitialExtent() { - return [Infinity, -Infinity]; - } - - function cloneChunk(originalChunk) { - var Ctor = originalChunk.constructor; // Only shallow clone is enough when Array. - - return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk); - } - - function prepareStore(store, dimIdx, dimType, end, append) { - var DataCtor = dataCtors[dimType || 'float']; - - if (append) { - var oldStore = store[dimIdx]; - var oldLen = oldStore && oldStore.length; - - if (!(oldLen === end)) { - var newStore = new DataCtor(end); // The cost of the copy is probably inconsiderable - // within the initial chunkSize. - - for (var j = 0; j < oldLen; j++) { - newStore[j] = oldStore[j]; - } - - store[dimIdx] = newStore; - } - } else { - store[dimIdx] = new DataCtor(end); - } - } - /** - * Basically, DataStore API keep immutable. - */ - - - var DataStore = - /** @class */ - function () { - function DataStore() { - this._chunks = []; // It will not be calculated until needed. - - this._rawExtent = []; - this._extent = []; - this._count = 0; - this._rawCount = 0; - this._calcDimNameToIdx = createHashMap(); - } - /** - * Initialize from data - */ - - - DataStore.prototype.initData = function (provider, inputDimensions, dimValueGetter) { - { - assert(isFunction(provider.getItem) && isFunction(provider.count), 'Invalid data provider.'); - } - this._provider = provider; // Clear - - this._chunks = []; - this._indices = null; - this.getRawIndex = this._getRawIdxIdentity; - var source = provider.getSource(); - var defaultGetter = this.defaultDimValueGetter = defaultDimValueGetters[source.sourceFormat]; // Default dim value getter - - this._dimValueGetter = dimValueGetter || defaultGetter; // Reset raw extent. - - this._rawExtent = []; - var willRetrieveDataByName = shouldRetrieveDataByName(source); - this._dimensions = map$1(inputDimensions, function (dim) { - { - if (willRetrieveDataByName) { - assert(dim.property != null); - } - } - return { - // Only pick these two props. Not leak other properties like orderMeta. - type: dim.type, - property: dim.property - }; - }); - - this._initDataFromProvider(0, provider.count()); - }; - - DataStore.prototype.getProvider = function () { - return this._provider; - }; - /** - * Caution: even when a `source` instance owned by a series, the created data store - * may still be shared by different sereis (the source hash does not use all `source` - * props, see `sourceManager`). In this case, the `source` props that are not used in - * hash (like `source.dimensionDefine`) probably only belongs to a certain series and - * thus should not be fetch here. - */ - - - DataStore.prototype.getSource = function () { - return this._provider.getSource(); - }; - /** - * @caution Only used in dataStack. - */ - - - DataStore.prototype.ensureCalculationDimension = function (dimName, type) { - var calcDimNameToIdx = this._calcDimNameToIdx; - var dimensions = this._dimensions; - var calcDimIdx = calcDimNameToIdx.get(dimName); - - if (calcDimIdx != null) { - if (dimensions[calcDimIdx].type === type) { - return calcDimIdx; - } - } else { - calcDimIdx = dimensions.length; - } - - dimensions[calcDimIdx] = { - type: type - }; - calcDimNameToIdx.set(dimName, calcDimIdx); - this._chunks[calcDimIdx] = new dataCtors[type || 'float'](this._rawCount); - this._rawExtent[calcDimIdx] = getInitialExtent(); - return calcDimIdx; - }; - - DataStore.prototype.collectOrdinalMeta = function (dimIdx, ordinalMeta) { - var chunk = this._chunks[dimIdx]; - var dim = this._dimensions[dimIdx]; - var rawExtents = this._rawExtent; - var offset = dim.ordinalOffset || 0; - var len = chunk.length; - - if (offset === 0) { - // We need to reset the rawExtent if collect is from start. - // Because this dimension may be guessed as number and calcuating a wrong extent. - rawExtents[dimIdx] = getInitialExtent(); - } - - var dimRawExtent = rawExtents[dimIdx]; // Parse from previous data offset. len may be changed after appendData - - for (var i = offset; i < len; i++) { - var val = chunk[i] = ordinalMeta.parseAndCollect(chunk[i]); - - if (!isNaN(val)) { - dimRawExtent[0] = Math.min(val, dimRawExtent[0]); - dimRawExtent[1] = Math.max(val, dimRawExtent[1]); - } - } - - dim.ordinalMeta = ordinalMeta; - dim.ordinalOffset = len; - dim.type = 'ordinal'; // Force to be ordinal - }; - - DataStore.prototype.getOrdinalMeta = function (dimIdx) { - var dimInfo = this._dimensions[dimIdx]; - var ordinalMeta = dimInfo.ordinalMeta; - return ordinalMeta; - }; - - DataStore.prototype.getDimensionProperty = function (dimIndex) { - var item = this._dimensions[dimIndex]; - return item && item.property; - }; - /** - * Caution: Can be only called on raw data (before `this._indices` created). - */ - - - DataStore.prototype.appendData = function (data) { - { - assert(!this._indices, 'appendData can only be called on raw data.'); - } - var provider = this._provider; - var start = this.count(); - provider.appendData(data); - var end = provider.count(); - - if (!provider.persistent) { - end += start; - } - - if (start < end) { - this._initDataFromProvider(start, end, true); - } - - return [start, end]; - }; - - DataStore.prototype.appendValues = function (values, minFillLen) { - var chunks = this._chunks; - var dimensions = this._dimensions; - var dimLen = dimensions.length; - var rawExtent = this._rawExtent; - var start = this.count(); - var end = start + Math.max(values.length, minFillLen || 0); - - for (var i = 0; i < dimLen; i++) { - var dim = dimensions[i]; - prepareStore(chunks, i, dim.type, end, true); - } - - var emptyDataItem = []; - - for (var idx = start; idx < end; idx++) { - var sourceIdx = idx - start; // Store the data by dimensions - - for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { - var dim = dimensions[dimIdx]; - var val = defaultDimValueGetters.arrayRows.call(this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx); - chunks[dimIdx][idx] = val; - var dimRawExtent = rawExtent[dimIdx]; - val < dimRawExtent[0] && (dimRawExtent[0] = val); - val > dimRawExtent[1] && (dimRawExtent[1] = val); - } - } - - this._rawCount = this._count = end; - return { - start: start, - end: end - }; - }; - - DataStore.prototype._initDataFromProvider = function (start, end, append) { - var provider = this._provider; - var chunks = this._chunks; - var dimensions = this._dimensions; - var dimLen = dimensions.length; - var rawExtent = this._rawExtent; - var dimNames = map$1(dimensions, function (dim) { - return dim.property; - }); - - for (var i = 0; i < dimLen; i++) { - var dim = dimensions[i]; - - if (!rawExtent[i]) { - rawExtent[i] = getInitialExtent(); - } - - prepareStore(chunks, i, dim.type, end, append); - } - - if (provider.fillStorage) { - provider.fillStorage(start, end, chunks, rawExtent); - } else { - var dataItem = []; - - for (var idx = start; idx < end; idx++) { - // NOTICE: Try not to write things into dataItem - dataItem = provider.getItem(idx, dataItem); // Each data item is value - // [1, 2] - // 2 - // Bar chart, line chart which uses category axis - // only gives the 'y' value. 'x' value is the indices of category - // Use a tempValue to normalize the value to be a (x, y) value - // Store the data by dimensions - - for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { - var dimStorage = chunks[dimIdx]; // PENDING NULL is empty or zero - - var val = this._dimValueGetter(dataItem, dimNames[dimIdx], idx, dimIdx); - - dimStorage[idx] = val; - var dimRawExtent = rawExtent[dimIdx]; - val < dimRawExtent[0] && (dimRawExtent[0] = val); - val > dimRawExtent[1] && (dimRawExtent[1] = val); - } - } - } - - if (!provider.persistent && provider.clean) { - // Clean unused data if data source is typed array. - provider.clean(); - } - - this._rawCount = this._count = end; // Reset data extent - - this._extent = []; - }; - - DataStore.prototype.count = function () { - return this._count; - }; - /** - * Get value. Return NaN if idx is out of range. - */ - - - DataStore.prototype.get = function (dim, idx) { - if (!(idx >= 0 && idx < this._count)) { - return NaN; - } - - var dimStore = this._chunks[dim]; - return dimStore ? dimStore[this.getRawIndex(idx)] : NaN; - }; - - DataStore.prototype.getValues = function (dimensions, idx) { - var values = []; - var dimArr = []; - - if (idx == null) { - idx = dimensions; // TODO get all from store? - - dimensions = []; // All dimensions - - for (var i = 0; i < this._dimensions.length; i++) { - dimArr.push(i); - } - } else { - dimArr = dimensions; - } - - for (var i = 0, len = dimArr.length; i < len; i++) { - values.push(this.get(dimArr[i], idx)); - } - - return values; - }; - /** - * @param dim concrete dim - */ - - - DataStore.prototype.getByRawIndex = function (dim, rawIdx) { - if (!(rawIdx >= 0 && rawIdx < this._rawCount)) { - return NaN; - } - - var dimStore = this._chunks[dim]; - return dimStore ? dimStore[rawIdx] : NaN; - }; - /** - * Get sum of data in one dimension - */ - - - DataStore.prototype.getSum = function (dim) { - var dimData = this._chunks[dim]; - var sum = 0; - - if (dimData) { - for (var i = 0, len = this.count(); i < len; i++) { - var value = this.get(dim, i); - - if (!isNaN(value)) { - sum += value; - } - } - } - - return sum; - }; - /** - * Get median of data in one dimension - */ - - - DataStore.prototype.getMedian = function (dim) { - var dimDataArray = []; // map all data of one dimension - - this.each([dim], function (val) { - if (!isNaN(val)) { - dimDataArray.push(val); - } - }); // TODO - // Use quick select? - - var sortedDimDataArray = dimDataArray.sort(function (a, b) { - return a - b; - }); - var len = this.count(); // calculate median - - return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2; - }; - /** - * Retrieve the index with given raw data index. - */ - - - DataStore.prototype.indexOfRawIndex = function (rawIndex) { - if (rawIndex >= this._rawCount || rawIndex < 0) { - return -1; - } - - if (!this._indices) { - return rawIndex; - } // Indices are ascending - - - var indices = this._indices; // If rawIndex === dataIndex - - var rawDataIndex = indices[rawIndex]; - - if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) { - return rawIndex; - } - - var left = 0; - var right = this._count - 1; - - while (left <= right) { - var mid = (left + right) / 2 | 0; - - if (indices[mid] < rawIndex) { - left = mid + 1; - } else if (indices[mid] > rawIndex) { - right = mid - 1; - } else { - return mid; - } - } - - return -1; - }; - /** - * Retrieve the index of nearest value. - * @param dim - * @param value - * @param [maxDistance=Infinity] - * @return If and only if multiple indices have - * the same value, they are put to the result. - */ - - - DataStore.prototype.indicesOfNearest = function (dim, value, maxDistance) { - var chunks = this._chunks; - var dimData = chunks[dim]; - var nearestIndices = []; - - if (!dimData) { - return nearestIndices; - } - - if (maxDistance == null) { - maxDistance = Infinity; - } - - var minDist = Infinity; - var minDiff = -1; - var nearestIndicesLen = 0; // Check the test case of `test/ut/spec/data/SeriesData.js`. - - for (var i = 0, len = this.count(); i < len; i++) { - var dataIndex = this.getRawIndex(i); - var diff = value - dimData[dataIndex]; - var dist = Math.abs(diff); - - if (dist <= maxDistance) { - // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`, - // we'd better not push both of them to `nearestIndices`, otherwise it is easy to - // get more than one item in `nearestIndices` (more specifically, in `tooltip`). - // So we choose the one that `diff >= 0` in this case. - // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them - // should be push to `nearestIndices`. - if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) { - minDist = dist; - minDiff = diff; - nearestIndicesLen = 0; - } - - if (diff === minDiff) { - nearestIndices[nearestIndicesLen++] = i; - } - } - } - - nearestIndices.length = nearestIndicesLen; - return nearestIndices; - }; - - DataStore.prototype.getIndices = function () { - var newIndices; - var indices = this._indices; - - if (indices) { - var Ctor = indices.constructor; - var thisCount = this._count; // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`. - - if (Ctor === Array) { - newIndices = new Ctor(thisCount); - - for (var i = 0; i < thisCount; i++) { - newIndices[i] = indices[i]; - } - } else { - newIndices = new Ctor(indices.buffer, 0, thisCount); - } - } else { - var Ctor = getIndicesCtor(this._rawCount); - newIndices = new Ctor(this.count()); - - for (var i = 0; i < newIndices.length; i++) { - newIndices[i] = i; - } - } - - return newIndices; - }; - /** - * Data filter. - */ - - - DataStore.prototype.filter = function (dims, cb) { - if (!this._count) { - return this; - } - - var newStore = this.clone(); - var count = newStore.count(); - var Ctor = getIndicesCtor(newStore._rawCount); - var newIndices = new Ctor(count); - var value = []; - var dimSize = dims.length; - var offset = 0; - var dim0 = dims[0]; - var chunks = newStore._chunks; - - for (var i = 0; i < count; i++) { - var keep = void 0; - var rawIdx = newStore.getRawIndex(i); // Simple optimization - - if (dimSize === 0) { - keep = cb(i); - } else if (dimSize === 1) { - var val = chunks[dim0][rawIdx]; - keep = cb(val, i); - } else { - var k = 0; - - for (; k < dimSize; k++) { - value[k] = chunks[dims[k]][rawIdx]; - } - - value[k] = i; - keep = cb.apply(null, value); - } - - if (keep) { - newIndices[offset++] = rawIdx; - } - } // Set indices after filtered. - - - if (offset < count) { - newStore._indices = newIndices; - } - - newStore._count = offset; // Reset data extent - - newStore._extent = []; - - newStore._updateGetRawIdx(); - - return newStore; - }; - /** - * Select data in range. (For optimization of filter) - * (Manually inline code, support 5 million data filtering in data zoom.) - */ - - - DataStore.prototype.selectRange = function (range) { - var newStore = this.clone(); - var len = newStore._count; - - if (!len) { - return this; - } - - var dims = keys(range); - var dimSize = dims.length; - - if (!dimSize) { - return this; - } - - var originalCount = newStore.count(); - var Ctor = getIndicesCtor(newStore._rawCount); - var newIndices = new Ctor(originalCount); - var offset = 0; - var dim0 = dims[0]; - var min = range[dim0][0]; - var max = range[dim0][1]; - var storeArr = newStore._chunks; - var quickFinished = false; - - if (!newStore._indices) { - // Extreme optimization for common case. About 2x faster in chrome. - var idx = 0; - - if (dimSize === 1) { - var dimStorage = storeArr[dims[0]]; - - for (var i = 0; i < len; i++) { - var val = dimStorage[i]; // NaN will not be filtered. Consider the case, in line chart, empty - // value indicates the line should be broken. But for the case like - // scatter plot, a data item with empty value will not be rendered, - // but the axis extent may be effected if some other dim of the data - // item has value. Fortunately it is not a significant negative effect. - - if (val >= min && val <= max || isNaN(val)) { - newIndices[offset++] = idx; - } - - idx++; - } - - quickFinished = true; - } else if (dimSize === 2) { - var dimStorage = storeArr[dims[0]]; - var dimStorage2 = storeArr[dims[1]]; - var min2 = range[dims[1]][0]; - var max2 = range[dims[1]][1]; - - for (var i = 0; i < len; i++) { - var val = dimStorage[i]; - var val2 = dimStorage2[i]; // Do not filter NaN, see comment above. - - if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) { - newIndices[offset++] = idx; - } - - idx++; - } - - quickFinished = true; - } - } - - if (!quickFinished) { - if (dimSize === 1) { - for (var i = 0; i < originalCount; i++) { - var rawIndex = newStore.getRawIndex(i); - var val = storeArr[dims[0]][rawIndex]; // Do not filter NaN, see comment above. - - if (val >= min && val <= max || isNaN(val)) { - newIndices[offset++] = rawIndex; - } - } - } else { - for (var i = 0; i < originalCount; i++) { - var keep = true; - var rawIndex = newStore.getRawIndex(i); - - for (var k = 0; k < dimSize; k++) { - var dimk = dims[k]; - var val = storeArr[dimk][rawIndex]; // Do not filter NaN, see comment above. - - if (val < range[dimk][0] || val > range[dimk][1]) { - keep = false; - } - } - - if (keep) { - newIndices[offset++] = newStore.getRawIndex(i); - } - } - } - } // Set indices after filtered. - - - if (offset < originalCount) { - newStore._indices = newIndices; - } - - newStore._count = offset; // Reset data extent - - newStore._extent = []; - - newStore._updateGetRawIdx(); - - return newStore; - }; // /** - // * Data mapping to a plain array - // */ - // mapArray(dims: DimensionIndex[], cb: MapArrayCb): any[] { - // const result: any[] = []; - // this.each(dims, function () { - // result.push(cb && (cb as MapArrayCb).apply(null, arguments)); - // }); - // return result; - // } - - /** - * Data mapping to a new List with given dimensions - */ - - - DataStore.prototype.map = function (dims, cb) { - // TODO only clone picked chunks. - var target = this.clone(dims); - - this._updateDims(target, dims, cb); - - return target; - }; - /** - * @caution Danger!! Only used in dataStack. - */ - - - DataStore.prototype.modify = function (dims, cb) { - this._updateDims(this, dims, cb); - }; - - DataStore.prototype._updateDims = function (target, dims, cb) { - var targetChunks = target._chunks; - var tmpRetValue = []; - var dimSize = dims.length; - var dataCount = target.count(); - var values = []; - var rawExtent = target._rawExtent; - - for (var i = 0; i < dims.length; i++) { - rawExtent[dims[i]] = getInitialExtent(); - } - - for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) { - var rawIndex = target.getRawIndex(dataIndex); - - for (var k = 0; k < dimSize; k++) { - values[k] = targetChunks[dims[k]][rawIndex]; - } - - values[dimSize] = dataIndex; - var retValue = cb && cb.apply(null, values); - - if (retValue != null) { - // a number or string (in oridinal dimension)? - if (typeof retValue !== 'object') { - tmpRetValue[0] = retValue; - retValue = tmpRetValue; - } - - for (var i = 0; i < retValue.length; i++) { - var dim = dims[i]; - var val = retValue[i]; - var rawExtentOnDim = rawExtent[dim]; - var dimStore = targetChunks[dim]; - - if (dimStore) { - dimStore[rawIndex] = val; - } - - if (val < rawExtentOnDim[0]) { - rawExtentOnDim[0] = val; - } - - if (val > rawExtentOnDim[1]) { - rawExtentOnDim[1] = val; - } - } - } - } - }; - /** - * Large data down sampling using largest-triangle-three-buckets - * @param {string} valueDimension - * @param {number} targetCount - */ - - - DataStore.prototype.lttbDownSample = function (valueDimension, rate) { - var target = this.clone([valueDimension], true); - var targetStorage = target._chunks; - var dimStore = targetStorage[valueDimension]; - var len = this.count(); - var sampledIndex = 0; - var frameSize = Math.floor(1 / rate); - var currentRawIndex = this.getRawIndex(0); - var maxArea; - var area; - var nextRawIndex; - var newIndices = new (getIndicesCtor(this._rawCount))(Math.min((Math.ceil(len / frameSize) + 2) * 2, len)); // First frame use the first data. - - newIndices[sampledIndex++] = currentRawIndex; - - for (var i = 1; i < len - 1; i += frameSize) { - var nextFrameStart = Math.min(i + frameSize, len - 1); - var nextFrameEnd = Math.min(i + frameSize * 2, len); - var avgX = (nextFrameEnd + nextFrameStart) / 2; - var avgY = 0; - - for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) { - var rawIndex = this.getRawIndex(idx); - var y = dimStore[rawIndex]; - - if (isNaN(y)) { - continue; - } - - avgY += y; - } - - avgY /= nextFrameEnd - nextFrameStart; - var frameStart = i; - var frameEnd = Math.min(i + frameSize, len); - var pointAX = i - 1; - var pointAY = dimStore[currentRawIndex]; - maxArea = -1; - nextRawIndex = frameStart; - var firstNaNIndex = -1; - var countNaN = 0; // Find a point from current frame that construct a triangle with largest area with previous selected point - // And the average of next frame. - - for (var idx = frameStart; idx < frameEnd; idx++) { - var rawIndex = this.getRawIndex(idx); - var y = dimStore[rawIndex]; - - if (isNaN(y)) { - countNaN++; - - if (firstNaNIndex < 0) { - firstNaNIndex = rawIndex; - } - - continue; - } // Calculate triangle area over three buckets - - - area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY)); - - if (area > maxArea) { - maxArea = area; - nextRawIndex = rawIndex; // Next a is this b - } - } - - if (countNaN > 0 && countNaN < frameEnd - frameStart) { - // Append first NaN point in every bucket. - // It is necessary to ensure the correct order of indices. - newIndices[sampledIndex++] = Math.min(firstNaNIndex, nextRawIndex); - nextRawIndex = Math.max(firstNaNIndex, nextRawIndex); - } - - newIndices[sampledIndex++] = nextRawIndex; - currentRawIndex = nextRawIndex; // This a is the next a (chosen b) - } // First frame use the last data. - - - newIndices[sampledIndex++] = this.getRawIndex(len - 1); - target._count = sampledIndex; - target._indices = newIndices; - target.getRawIndex = this._getRawIdx; - return target; - }; - /** - * Large data down sampling on given dimension - * @param sampleIndex Sample index for name and id - */ - - - DataStore.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) { - var target = this.clone([dimension], true); - var targetStorage = target._chunks; - var frameValues = []; - var frameSize = Math.floor(1 / rate); - var dimStore = targetStorage[dimension]; - var len = this.count(); - var rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent(); - var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize)); - var offset = 0; - - for (var i = 0; i < len; i += frameSize) { - // Last frame - if (frameSize > len - i) { - frameSize = len - i; - frameValues.length = frameSize; - } - - for (var k = 0; k < frameSize; k++) { - var dataIdx = this.getRawIndex(i + k); - frameValues[k] = dimStore[dataIdx]; - } - - var value = sampleValue(frameValues); - var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); // Only write value on the filtered data - - dimStore[sampleFrameIdx] = value; - - if (value < rawExtentOnDim[0]) { - rawExtentOnDim[0] = value; - } - - if (value > rawExtentOnDim[1]) { - rawExtentOnDim[1] = value; - } - - newIndices[offset++] = sampleFrameIdx; - } - - target._count = offset; - target._indices = newIndices; - - target._updateGetRawIdx(); - - return target; - }; - /** - * Data iteration - * @param ctx default this - * @example - * list.each('x', function (x, idx) {}); - * list.each(['x', 'y'], function (x, y, idx) {}); - * list.each(function (idx) {}) - */ - - - DataStore.prototype.each = function (dims, cb) { - if (!this._count) { - return; - } - - var dimSize = dims.length; - var chunks = this._chunks; - - for (var i = 0, len = this.count(); i < len; i++) { - var rawIdx = this.getRawIndex(i); // Simple optimization - - switch (dimSize) { - case 0: - cb(i); - break; - - case 1: - cb(chunks[dims[0]][rawIdx], i); - break; - - case 2: - cb(chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i); - break; - - default: - var k = 0; - var value = []; - - for (; k < dimSize; k++) { - value[k] = chunks[dims[k]][rawIdx]; - } // Index - - - value[k] = i; - cb.apply(null, value); - } - } - }; - /** - * Get extent of data in one dimension - */ - - - DataStore.prototype.getDataExtent = function (dim) { - // Make sure use concrete dim as cache name. - var dimData = this._chunks[dim]; - var initialExtent = getInitialExtent(); - - if (!dimData) { - return initialExtent; - } // Make more strict checkings to ensure hitting cache. - - - var currEnd = this.count(); // Consider the most cases when using data zoom, `getDataExtent` - // happened before filtering. We cache raw extent, which is not - // necessary to be cleared and recalculated when restore data. - - var useRaw = !this._indices; - var dimExtent; - - if (useRaw) { - return this._rawExtent[dim].slice(); - } - - dimExtent = this._extent[dim]; - - if (dimExtent) { - return dimExtent.slice(); - } - - dimExtent = initialExtent; - var min = dimExtent[0]; - var max = dimExtent[1]; - - for (var i = 0; i < currEnd; i++) { - var rawIdx = this.getRawIndex(i); - var value = dimData[rawIdx]; - value < min && (min = value); - value > max && (max = value); - } - - dimExtent = [min, max]; - this._extent[dim] = dimExtent; - return dimExtent; - }; - /** - * Get raw data item - */ - - - DataStore.prototype.getRawDataItem = function (idx) { - var rawIdx = this.getRawIndex(idx); - - if (!this._provider.persistent) { - var val = []; - var chunks = this._chunks; - - for (var i = 0; i < chunks.length; i++) { - val.push(chunks[i][rawIdx]); - } - - return val; - } else { - return this._provider.getItem(rawIdx); - } - }; - /** - * Clone shallow. - * - * @param clonedDims Determine which dims to clone. Will share the data if not specified. - */ - - - DataStore.prototype.clone = function (clonedDims, ignoreIndices) { - var target = new DataStore(); - var chunks = this._chunks; - var clonedDimsMap = clonedDims && reduce(clonedDims, function (obj, dimIdx) { - obj[dimIdx] = true; - return obj; - }, {}); - - if (clonedDimsMap) { - for (var i = 0; i < chunks.length; i++) { - // Not clone if dim is not picked. - target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]); - } - } else { - target._chunks = chunks; - } - - this._copyCommonProps(target); - - if (!ignoreIndices) { - target._indices = this._cloneIndices(); - } - - target._updateGetRawIdx(); - - return target; - }; - - DataStore.prototype._copyCommonProps = function (target) { - target._count = this._count; - target._rawCount = this._rawCount; - target._provider = this._provider; - target._dimensions = this._dimensions; - target._extent = clone$3(this._extent); - target._rawExtent = clone$3(this._rawExtent); - }; - - DataStore.prototype._cloneIndices = function () { - if (this._indices) { - var Ctor = this._indices.constructor; - var indices = void 0; - - if (Ctor === Array) { - var thisCount = this._indices.length; - indices = new Ctor(thisCount); - - for (var i = 0; i < thisCount; i++) { - indices[i] = this._indices[i]; - } - } else { - indices = new Ctor(this._indices); - } - - return indices; - } - - return null; - }; - - DataStore.prototype._getRawIdxIdentity = function (idx) { - return idx; - }; - - DataStore.prototype._getRawIdx = function (idx) { - if (idx < this._count && idx >= 0) { - return this._indices[idx]; - } - - return -1; - }; - - DataStore.prototype._updateGetRawIdx = function () { - this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity; - }; - - DataStore.internalField = function () { - function getDimValueSimply(dataItem, property, dataIndex, dimIndex) { - return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]); - } - - defaultDimValueGetters = { - arrayRows: getDimValueSimply, - objectRows: function (dataItem, property, dataIndex, dimIndex) { - return parseDataValue(dataItem[property], this._dimensions[dimIndex]); - }, - keyedColumns: getDimValueSimply, - original: function (dataItem, property, dataIndex, dimIndex) { - // Performance sensitive, do not use modelUtil.getDataItemValue. - // If dataItem is an plain object with no value field, the let `value` - // will be assigned with the object, but it will be tread correctly - // in the `convertValue`. - var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); - return parseDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array. - : value, this._dimensions[dimIndex]); - }, - typedArray: function (dataItem, property, dataIndex, dimIndex) { - return dataItem[dimIndex]; - } - }; - }(); - - return DataStore; - }(); - /** - * [REQUIREMENT_MEMO]: - * (0) `metaRawOption` means `dimensions`/`sourceHeader`/`seriesLayoutBy` in raw option. - * (1) Keep support the feature: `metaRawOption` can be specified both on `series` and - * `root-dataset`. Them on `series` has higher priority. - * (2) Do not support to set `metaRawOption` on a `non-root-dataset`, because it might - * confuse users: whether those props indicate how to visit the upstream source or visit - * the transform result source, and some transforms has nothing to do with these props, - * and some transforms might have multiple upstream. - * (3) Transforms should specify `metaRawOption` in each output, just like they can be - * declared in `root-dataset`. - * (4) At present only support visit source in `SERIES_LAYOUT_BY_COLUMN` in transforms. - * That is for reducing complexity in transforms. - * PENDING: Whether to provide transposition transform? - * - * [IMPLEMENTAION_MEMO]: - * "sourceVisitConfig" are calculated from `metaRawOption` and `data`. - * They will not be calculated until `source` is about to be visited (to prevent from - * duplicate calcuation). `source` is visited only in series and input to transforms. - * - * [DIMENSION_INHERIT_RULE]: - * By default the dimensions are inherited from ancestors, unless a transform return - * a new dimensions definition. - * Consider the case: - * ```js - * dataset: [{ - * source: [ ['Product', 'Sales', 'Prise'], ['Cookies', 321, 44.21], ...] - * }, { - * transform: { type: 'filter', ... } - * }] - * dataset: [{ - * dimension: ['Product', 'Sales', 'Prise'], - * source: [ ['Cookies', 321, 44.21], ...] - * }, { - * transform: { type: 'filter', ... } - * }] - * ``` - * The two types of option should have the same behavior after transform. - * - * - * [SCENARIO]: - * (1) Provide source data directly: - * ```js - * series: { - * encode: {...}, - * dimensions: [...] - * seriesLayoutBy: 'row', - * data: [[...]] - * } - * ``` - * (2) Series refer to dataset. - * ```js - * series: [{ - * encode: {...} - * // Ignore datasetIndex means `datasetIndex: 0` - * // and the dimensions defination in dataset is used - * }, { - * encode: {...}, - * seriesLayoutBy: 'column', - * datasetIndex: 1 - * }] - * ``` - * (3) dataset transform - * ```js - * dataset: [{ - * source: [...] - * }, { - * source: [...] - * }, { - * // By default from 0. - * transform: { type: 'filter', config: {...} } - * }, { - * // Piped. - * transform: [ - * { type: 'filter', config: {...} }, - * { type: 'sort', config: {...} } - * ] - * }, { - * id: 'regressionData', - * fromDatasetIndex: 1, - * // Third-party transform - * transform: { type: 'ecStat:regression', config: {...} } - * }, { - * // retrieve the extra result. - * id: 'regressionFormula', - * fromDatasetId: 'regressionData', - * fromTransformResult: 1 - * }] - * ``` - */ - - - var SourceManager = - /** @class */ - function () { - function SourceManager(sourceHost) { - // Cached source. Do not repeat calculating if not dirty. - this._sourceList = []; - this._storeList = []; // version sign of each upstream source manager. - - this._upstreamSignList = []; - this._versionSignBase = 0; - this._dirty = true; - this._sourceHost = sourceHost; - } - /** - * Mark dirty. - */ - - - SourceManager.prototype.dirty = function () { - this._setLocalSource([], []); - - this._storeList = []; - this._dirty = true; - }; - - SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) { - this._sourceList = sourceList; - this._upstreamSignList = upstreamSignList; - this._versionSignBase++; - - if (this._versionSignBase > 9e10) { - this._versionSignBase = 0; - } - }; - /** - * For detecting whether the upstream source is dirty, so that - * the local cached source (in `_sourceList`) should be discarded. - */ - - - SourceManager.prototype._getVersionSign = function () { - return this._sourceHost.uid + '_' + this._versionSignBase; - }; - /** - * Always return a source instance. Otherwise throw error. - */ - - - SourceManager.prototype.prepareSource = function () { - // For the case that call `setOption` multiple time but no data changed, - // cache the result source to prevent from repeating transform. - if (this._isDirty()) { - this._createSource(); - - this._dirty = false; - } - }; - - SourceManager.prototype._createSource = function () { - this._setLocalSource([], []); - - var sourceHost = this._sourceHost; - - var upSourceMgrList = this._getUpstreamSourceManagers(); - - var hasUpstream = !!upSourceMgrList.length; - var resultSourceList; - var upstreamSignList; - - if (isSeries(sourceHost)) { - var seriesModel = sourceHost; - var data = void 0; - var sourceFormat = void 0; - var upSource = void 0; // Has upstream dataset - - if (hasUpstream) { - var upSourceMgr = upSourceMgrList[0]; - upSourceMgr.prepareSource(); - upSource = upSourceMgr.getSource(); - data = upSource.data; - sourceFormat = upSource.sourceFormat; - upstreamSignList = [upSourceMgr._getVersionSign()]; - } // Series data is from own. - else { - data = seriesModel.get('data', true); - sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL; - upstreamSignList = []; - } // See [REQUIREMENT_MEMO], merge settings on series and parent dataset if it is root. - - - var newMetaRawOption = this._getSourceMetaRawOption() || {}; - var upMetaRawOption = upSource && upSource.metaRawOption || {}; - var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption.seriesLayoutBy) || null; - var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption.sourceHeader); // Note here we should not use `upSource.dimensionsDefine`. Consider the case: - // `upSource.dimensionsDefine` is detected by `seriesLayoutBy: 'column'`, - // but series need `seriesLayoutBy: 'row'`. - - var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption.dimensions); // We share source with dataset as much as possible - // to avoid extra memory cost of high dimensional data. - - var needsCreateSource = seriesLayoutBy !== upMetaRawOption.seriesLayoutBy || !!sourceHeader !== !!upMetaRawOption.sourceHeader || dimensions; - resultSourceList = needsCreateSource ? [createSource(data, { - seriesLayoutBy: seriesLayoutBy, - sourceHeader: sourceHeader, - dimensions: dimensions - }, sourceFormat)] : []; - } else { - var datasetModel = sourceHost; // Has upstream dataset. - - if (hasUpstream) { - var result = this._applyTransform(upSourceMgrList); - - resultSourceList = result.sourceList; - upstreamSignList = result.upstreamSignList; - } // Is root dataset. - else { - var sourceData = datasetModel.get('source', true); - resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null)]; - upstreamSignList = []; - } - } - - { - assert(resultSourceList && upstreamSignList); - } - - this._setLocalSource(resultSourceList, upstreamSignList); - }; - - SourceManager.prototype._applyTransform = function (upMgrList) { - var datasetModel = this._sourceHost; - var transformOption = datasetModel.get('transform', true); - var fromTransformResult = datasetModel.get('fromTransformResult', true); - { - assert(fromTransformResult != null || transformOption != null); - } - - if (fromTransformResult != null) { - var errMsg = ''; - - if (upMgrList.length !== 1) { - { - errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset'; - } - doThrow(errMsg); - } - } - - var sourceList; - var upSourceList = []; - var upstreamSignList = []; - each$4(upMgrList, function (upMgr) { - upMgr.prepareSource(); - var upSource = upMgr.getSource(fromTransformResult || 0); - var errMsg = ''; - - if (fromTransformResult != null && !upSource) { - { - errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult; - } - doThrow(errMsg); - } - - upSourceList.push(upSource); - upstreamSignList.push(upMgr._getVersionSign()); - }); - - if (transformOption) { - sourceList = applyDataTransform(transformOption, upSourceList, { - datasetIndex: datasetModel.componentIndex - }); - } else if (fromTransformResult != null) { - sourceList = [cloneSourceShallow(upSourceList[0])]; - } - - return { - sourceList: sourceList, - upstreamSignList: upstreamSignList - }; - }; - - SourceManager.prototype._isDirty = function () { - if (this._dirty) { - return true; - } // All sourceList is from the some upstream. - - - var upSourceMgrList = this._getUpstreamSourceManagers(); - - for (var i = 0; i < upSourceMgrList.length; i++) { - var upSrcMgr = upSourceMgrList[i]; - - if ( // Consider the case that there is ancestor diry, call it recursively. - // The performance is probably not an issue because usually the chain is not long. - upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) { - return true; - } - } - }; - /** - * @param sourceIndex By default 0, means "main source". - * In most cases there is only one source. - */ - - - SourceManager.prototype.getSource = function (sourceIndex) { - sourceIndex = sourceIndex || 0; - var source = this._sourceList[sourceIndex]; - - if (!source) { - // Series may share source instance with dataset. - var upSourceMgrList = this._getUpstreamSourceManagers(); - - return upSourceMgrList[0] && upSourceMgrList[0].getSource(sourceIndex); - } - - return source; - }; - /** - * - * Get a data store which can be shared across series. - * Only available for series. - * - * @param seriesDimRequest Dimensions that are generated in series. - * Should have been sorted by `storeDimIndex` asc. - */ - - - SourceManager.prototype.getSharedDataStore = function (seriesDimRequest) { - { - assert(isSeries(this._sourceHost), 'Can only call getDataStore on series source manager.'); - } - var schema = seriesDimRequest.makeStoreSchema(); - return this._innerGetDataStore(schema.dimensions, seriesDimRequest.source, schema.hash); - }; - - SourceManager.prototype._innerGetDataStore = function (storeDims, seriesSource, sourceReadKey) { - // TODO Can use other sourceIndex? - var sourceIndex = 0; - var storeList = this._storeList; - var cachedStoreMap = storeList[sourceIndex]; - - if (!cachedStoreMap) { - cachedStoreMap = storeList[sourceIndex] = {}; - } - - var cachedStore = cachedStoreMap[sourceReadKey]; - - if (!cachedStore) { - var upSourceMgr = this._getUpstreamSourceManagers()[0]; - - if (isSeries(this._sourceHost) && upSourceMgr) { - cachedStore = upSourceMgr._innerGetDataStore(storeDims, seriesSource, sourceReadKey); - } else { - cachedStore = new DataStore(); // Always create store from source of series. - - cachedStore.initData(new DefaultDataProvider(seriesSource, storeDims.length), storeDims); - } - - cachedStoreMap[sourceReadKey] = cachedStore; - } - - return cachedStore; - }; - /** - * PENDING: Is it fast enough? - * If no upstream, return empty array. - */ - - - SourceManager.prototype._getUpstreamSourceManagers = function () { - // Always get the relationship from the raw option. - // Do not cache the link of the dependency graph, so that - // there is no need to update them when change happens. - var sourceHost = this._sourceHost; - - if (isSeries(sourceHost)) { - var datasetModel = querySeriesUpstreamDatasetModel(sourceHost); - return !datasetModel ? [] : [datasetModel.getSourceManager()]; - } else { - return map$1(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) { - return datasetModel.getSourceManager(); - }); - } - }; - - SourceManager.prototype._getSourceMetaRawOption = function () { - var sourceHost = this._sourceHost; - var seriesLayoutBy; - var sourceHeader; - var dimensions; - - if (isSeries(sourceHost)) { - seriesLayoutBy = sourceHost.get('seriesLayoutBy', true); - sourceHeader = sourceHost.get('sourceHeader', true); - dimensions = sourceHost.get('dimensions', true); - } // See [REQUIREMENT_MEMO], `non-root-dataset` do not support them. - else if (!this._getUpstreamSourceManagers().length) { - var model = sourceHost; - seriesLayoutBy = model.get('seriesLayoutBy', true); - sourceHeader = model.get('sourceHeader', true); - dimensions = model.get('dimensions', true); - } - - return { - seriesLayoutBy: seriesLayoutBy, - sourceHeader: sourceHeader, - dimensions: dimensions - }; - }; - - return SourceManager; - }(); // Call this method after `super.init` and `super.mergeOption` to - // disable the transform merge, but do not disable transform clone from rawOption. - - - function disableTransformOptionMerge(datasetModel) { - var transformOption = datasetModel.option.transform; - transformOption && setAsPrimitive(datasetModel.option.transform); - } - - function isSeries(sourceHost) { - // Avoid circular dependency with Series.ts - return sourceHost.mainType === 'series'; - } - - function doThrow(errMsg) { - throw new Error(errMsg); - } - - var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1'; // TODO: more textStyle option - - function getTooltipTextStyle(textStyle, renderMode) { - var nameFontColor = textStyle.color || '#6e7079'; - var nameFontSize = textStyle.fontSize || 12; - var nameFontWeight = textStyle.fontWeight || '400'; - var valueFontColor = textStyle.color || '#464646'; - var valueFontSize = textStyle.fontSize || 14; - var valueFontWeight = textStyle.fontWeight || '900'; - - if (renderMode === 'html') { - // `textStyle` is probably from user input, should be encoded to reduce security risk. - return { - // eslint-disable-next-line max-len - nameStyle: "font-size:" + encodeHTML(nameFontSize + '') + "px;color:" + encodeHTML(nameFontColor) + ";font-weight:" + encodeHTML(nameFontWeight + ''), - // eslint-disable-next-line max-len - valueStyle: "font-size:" + encodeHTML(valueFontSize + '') + "px;color:" + encodeHTML(valueFontColor) + ";font-weight:" + encodeHTML(valueFontWeight + '') - }; - } else { - return { - nameStyle: { - fontSize: nameFontSize, - fill: nameFontColor, - fontWeight: nameFontWeight - }, - valueStyle: { - fontSize: valueFontSize, - fill: valueFontColor, - fontWeight: valueFontWeight - } - }; - } - } // See `TooltipMarkupLayoutIntent['innerGapLevel']`. - // (value from UI design) - - - var HTML_GAPS = [0, 10, 20, 30]; - var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n']; // eslint-disable-next-line max-len - - function createTooltipMarkup(type, option) { - option.type = type; - return option; - } - - function isSectionFragment(frag) { - return frag.type === 'section'; - } - - function getBuilder(frag) { - return isSectionFragment(frag) ? buildSection : buildNameValue; - } - - function getBlockGapLevel(frag) { - if (isSectionFragment(frag)) { - var gapLevel_1 = 0; - var subBlockLen = frag.blocks.length; - var hasInnerGap_1 = subBlockLen > 1 || subBlockLen > 0 && !frag.noHeader; - each$4(frag.blocks, function (subBlock) { - var subGapLevel = getBlockGapLevel(subBlock); // If the some of the sub-blocks have some gaps (like 10px) inside, this block - // should use a larger gap (like 20px) to distinguish those sub-blocks. - - if (subGapLevel >= gapLevel_1) { - gapLevel_1 = subGapLevel + +(hasInnerGap_1 && ( // 0 always can not be readable gap level. - !subGapLevel // If no header, always keep the sub gap level. Otherwise - // look weird in case `multipleSeries`. - || isSectionFragment(subBlock) && !subBlock.noHeader)); - } - }); - return gapLevel_1; - } - - return 0; - } - - function buildSection(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { - var noHeader = fragment.noHeader; - var gaps = getGap(getBlockGapLevel(fragment)); - var subMarkupTextList = []; - var subBlocks = fragment.blocks || []; - assert(!subBlocks || isArray(subBlocks)); - subBlocks = subBlocks || []; - var orderMode = ctx.orderMode; - - if (fragment.sortBlocks && orderMode) { - subBlocks = subBlocks.slice(); - var orderMap = { - valueAsc: 'asc', - valueDesc: 'desc' - }; - - if (hasOwn(orderMap, orderMode)) { - var comparator_1 = new SortOrderComparator(orderMap[orderMode], null); - subBlocks.sort(function (a, b) { - return comparator_1.evaluate(a.sortParam, b.sortParam); - }); - } // FIXME 'seriesDesc' necessary? - else if (orderMode === 'seriesDesc') { - subBlocks.reverse(); - } - } - - each$4(subBlocks, function (subBlock, idx) { - var valueFormatter = fragment.valueFormatter; - var subMarkupText = getBuilder(subBlock)( // Inherit valueFormatter - valueFormatter ? extend(extend({}, ctx), { - valueFormatter: valueFormatter - }) : ctx, subBlock, idx > 0 ? gaps.html : 0, toolTipTextStyle); - subMarkupText != null && subMarkupTextList.push(subMarkupText); - }); - var subMarkupText = ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), noHeader ? topMarginForOuterGap : gaps.html); - - if (noHeader) { - return subMarkupText; - } - - var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC); - var nameStyle = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode).nameStyle; - - if (ctx.renderMode === 'richText') { - return wrapInlineNameRichText(ctx, displayableHeader, nameStyle) + gaps.richText + subMarkupText; - } else { - return wrapBlockHTML("
" + encodeHTML(displayableHeader) + '
' + subMarkupText, topMarginForOuterGap); - } - } - - function buildNameValue(ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { - var renderMode = ctx.renderMode; - var noName = fragment.noName; - var noValue = fragment.noValue; - var noMarker = !fragment.markerType; - var name = fragment.name; - var useUTC = ctx.useUTC; - - var valueFormatter = fragment.valueFormatter || ctx.valueFormatter || function (value) { - value = isArray(value) ? value : [value]; - return map$1(value, function (val, idx) { - return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC); - }); - }; - - if (noName && noValue) { - return; - } - - var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode); - var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC); - var valueTypeOption = fragment.valueType; - var readableValueList = noValue ? [] : valueFormatter(fragment.value, fragment.dataIndex); - var valueAlignRight = !noMarker || !noName; // It little weird if only value next to marker but far from marker. - - var valueCloseToMarker = !noMarker && noName; - - var _a = getTooltipTextStyle(toolTipTextStyle, renderMode), - nameStyle = _a.nameStyle, - valueStyle = _a.valueStyle; - - return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle)) // Value has commas inside, so use ' ' as delimiter for multiple values. - + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)), topMarginForOuterGap); - } - /** - * @return markupText. null/undefined means no content. - */ - - - function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC, toolTipTextStyle) { - if (!fragment) { - return; - } - - var builder = getBuilder(fragment); - var ctx = { - useUTC: useUTC, - renderMode: renderMode, - orderMode: orderMode, - markupStyleCreator: markupStyleCreator, - valueFormatter: fragment.valueFormatter - }; - return builder(ctx, fragment, 0, toolTipTextStyle); - } - - function getGap(gapLevel) { - return { - html: HTML_GAPS[gapLevel], - richText: RICH_TEXT_GAPS[gapLevel] - }; - } - - function wrapBlockHTML(encodedContent, topGap) { - var clearfix = '
'; - var marginCSS = "margin: " + topGap + "px 0 0"; - return "
" + encodedContent + clearfix + '
'; - } - - function wrapInlineNameHTML(name, leftHasMarker, style) { - var marginCss = leftHasMarker ? 'margin-left:2px' : ''; - return "" + encodeHTML(name) + ''; - } - - function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker, style) { - // Do not too close to marker, considering there are multiple values separated by spaces. - var paddingStr = valueCloseToMarker ? '10px' : '20px'; - var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : ''; - valueList = isArray(valueList) ? valueList : [valueList]; - return "" // Value has commas inside, so use ' ' as delimiter for multiple values. - + map$1(valueList, function (value) { - return encodeHTML(value); - }).join('  ') + ''; - } - - function wrapInlineNameRichText(ctx, name, style) { - return ctx.markupStyleCreator.wrapRichTextStyle(name, style); - } - - function wrapInlineValueRichText(ctx, values, alignRight, valueCloseToMarker, style) { - var styles = [style]; - var paddingLeft = valueCloseToMarker ? 10 : 20; - alignRight && styles.push({ - padding: [0, 0, 0, paddingLeft], - align: 'right' - }); // Value has commas inside, so use ' ' as delimiter for multiple values. - - return ctx.markupStyleCreator.wrapRichTextStyle(isArray(values) ? values.join(' ') : values, styles); - } - - function retrieveVisualColorForTooltipMarker(series, dataIndex) { - var style = series.getData().getItemVisual(dataIndex, 'style'); - var color = style[series.visualDrawType]; - return convertToColorString(color); - } - - function getPaddingFromTooltipModel(model, renderMode) { - var padding = model.get('padding'); - return padding != null ? padding // We give slightly different to look pretty. - : renderMode === 'richText' ? [8, 10] : 10; - } - /** - * The major feature is generate styles for `renderMode: 'richText'`. - * But it also serves `renderMode: 'html'` to provide - * "renderMode-independent" API. - */ - - - var TooltipMarkupStyleCreator = - /** @class */ - function () { - function TooltipMarkupStyleCreator() { - this.richTextStyles = {}; // Notice that "generate a style name" usually happens repeatedly when mouse is moving and - // a tooltip is displayed. So we put the `_nextStyleNameId` as a member of each creator - // rather than static shared by all creators (which will cause it increase to fast). - - this._nextStyleNameId = getRandomIdBase(); - } - - TooltipMarkupStyleCreator.prototype._generateStyleName = function () { - return '__EC_aUTo_' + this._nextStyleNameId++; - }; - - TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) { - var markerId = renderMode === 'richText' ? this._generateStyleName() : null; - var marker = getTooltipMarker({ - color: colorStr, - type: markerType, - renderMode: renderMode, - markerId: markerId - }); - - if (isString(marker)) { - return marker; - } else { - { - assert(markerId); - } - this.richTextStyles[markerId] = marker.style; - return marker.content; - } - }; - /** - * @usage - * ```ts - * const styledText = markupStyleCreator.wrapRichTextStyle([ - * // The styles will be auto merged. - * { - * fontSize: 12, - * color: 'blue' - * }, - * { - * padding: 20 - * } - * ]); - * ``` - */ - - - TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) { - var finalStl = {}; - - if (isArray(styles)) { - each$4(styles, function (stl) { - return extend(finalStl, stl); - }); - } else { - extend(finalStl, styles); - } - - var styleName = this._generateStyleName(); - - this.richTextStyles[styleName] = finalStl; - return "{" + styleName + "|" + text + "}"; - }; - - return TooltipMarkupStyleCreator; - }(); - - function defaultSeriesFormatTooltip(opt) { - var series = opt.series; - var dataIndex = opt.dataIndex; - var multipleSeries = opt.multipleSeries; - var data = series.getData(); - var tooltipDims = data.mapDimensionsAll('defaultedTooltip'); - var tooltipDimLen = tooltipDims.length; - var value = series.getRawValue(dataIndex); - var isValueArr = isArray(value); - var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); // Complicated rule for pretty tooltip. - - var inlineValue; - var inlineValueType; - var subBlocks; - var sortParam; - - if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) { - var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor); - inlineValue = formatArrResult.inlineValues; - inlineValueType = formatArrResult.inlineValueTypes; - subBlocks = formatArrResult.blocks; // Only support tooltip sort by the first inline value. It's enough in most cases. - - sortParam = formatArrResult.inlineValues[0]; - } else if (tooltipDimLen) { - var dimInfo = data.getDimensionInfo(tooltipDims[0]); - sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]); - inlineValueType = dimInfo.type; - } else { - sortParam = inlineValue = isValueArr ? value[0] : value; - } // Do not show generated series name. It might not be readable. - - - var seriesNameSpecified = isNameSpecified(series); - var seriesName = seriesNameSpecified && series.name || ''; - var itemName = data.getName(dataIndex); - var inlineName = multipleSeries ? seriesName : itemName; - return createTooltipMarkup('section', { - header: seriesName, - // When series name is not specified, do not show a header line with only '-'. - // This case always happens in tooltip.trigger: 'item'. - noHeader: multipleSeries || !seriesNameSpecified, - sortParam: sortParam, - blocks: [createTooltipMarkup('nameValue', { - markerType: 'item', - markerColor: markerColor, - // Do not mix display seriesName and itemName in one tooltip, - // which might confuses users. - name: inlineName, - // name dimension might be auto assigned, where the name might - // be not readable. So we check trim here. - noName: !trim(inlineName), - value: inlineValue, - valueType: inlineValueType, - dataIndex: dataIndex - })].concat(subBlocks || []) - }); - } - - function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) { - // check: category-no-encode-has-axis-data in dataset.html - var data = series.getData(); - var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) { - var dimItem = data.getDimensionInfo(idx); - return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null; - }, false); - var inlineValues = []; - var inlineValueTypes = []; - var blocks = []; - tooltipDims.length ? each$4(tooltipDims, function (dim) { - setEachItem(retrieveRawValue(data, dataIndex, dim), dim); - }) // By default, all dims is used on tooltip. - : each$4(value, setEachItem); - - function setEachItem(val, dim) { - var dimInfo = data.getDimensionInfo(dim); // If `dimInfo.tooltip` is not set, show tooltip. - - if (!dimInfo || dimInfo.otherDims.tooltip === false) { - return; - } - - if (isValueMultipleLine) { - blocks.push(createTooltipMarkup('nameValue', { - markerType: 'subItem', - markerColor: colorStr, - name: dimInfo.displayName, - value: val, - valueType: dimInfo.type - })); - } else { - inlineValues.push(val); - inlineValueTypes.push(dimInfo.type); - } - } - - return { - inlineValues: inlineValues, - inlineValueTypes: inlineValueTypes, - blocks: blocks - }; - } - - var inner$8 = makeInner(); - - function getSelectionKey(data, dataIndex) { - return data.getName(dataIndex) || data.getId(dataIndex); - } - - var SERIES_UNIVERSAL_TRANSITION_PROP = '__universalTransitionEnabled'; - - var SeriesModel = - /** @class */ - function (_super) { - __extends(SeriesModel, _super); - - function SeriesModel() { - // [Caution]: Because this class or desecendants can be used as `XXX.extend(subProto)`, - // the class members must not be initialized in constructor or declaration place. - // Otherwise there is bad case: - // class A {xxx = 1;} - // enableClassExtend(A); - // class B extends A {} - // var C = B.extend({xxx: 5}); - // var c = new C(); - // console.log(c.xxx); // expect 5 but always 1. - var _this = _super !== null && _super.apply(this, arguments) || this; // --------------------------------------- - // Props about data selection - // --------------------------------------- - - - _this._selectedDataIndicesMap = {}; - return _this; - } - - SeriesModel.prototype.init = function (option, parentModel, ecModel) { - this.seriesIndex = this.componentIndex; - this.dataTask = createTask({ - count: dataTaskCount, - reset: dataTaskReset - }); - this.dataTask.context = { - model: this - }; - this.mergeDefaultAndTheme(option, ecModel); - var sourceManager = inner$8(this).sourceManager = new SourceManager(this); - sourceManager.prepareSource(); - var data = this.getInitialData(option, ecModel); - wrapData(data, this); - this.dataTask.context.data = data; - { - assert(data, 'getInitialData returned invalid data.'); - } - inner$8(this).dataBeforeProcessed = data; // If we reverse the order (make data firstly, and then make - // dataBeforeProcessed by cloneShallow), cloneShallow will - // cause data.graph.data !== data when using - // module:echarts/data/Graph or module:echarts/data/Tree. - // See module:echarts/data/helper/linkSeriesData - // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model - // init or merge stage, because the data can be restored. So we do not `restoreData` - // and `setData` here, which forbids calling `seriesModel.getData()` in this stage. - // Call `seriesModel.getRawData()` instead. - // this.restoreData(); - - autoSeriesName(this); - - this._initSelectedMapFromData(data); - }; - /** - * Util for merge default and theme to option - */ - - - SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { - var layoutMode = fetchLayoutMode(this); - var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; // Backward compat: using subType on theme. - // But if name duplicate between series subType - // (for example: parallel) add component mainType, - // add suffix 'Series'. - - var themeSubType = this.subType; - - if (ComponentModel.hasClass(themeSubType)) { - themeSubType += 'Series'; - } - - merge(option, ecModel.getTheme().get(this.subType)); - merge(option, this.getDefaultOption()); // Default label emphasis `show` - - defaultEmphasis(option, 'label', ['show']); - this.fillDataTextStyle(option.data); - - if (layoutMode) { - mergeLayoutParam(option, inputPositionParams, layoutMode); - } - }; - - SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) { - // this.settingTask.dirty(); - newSeriesOption = merge(this.option, newSeriesOption, true); - this.fillDataTextStyle(newSeriesOption.data); - var layoutMode = fetchLayoutMode(this); - - if (layoutMode) { - mergeLayoutParam(this.option, newSeriesOption, layoutMode); - } - - var sourceManager = inner$8(this).sourceManager; - sourceManager.dirty(); - sourceManager.prepareSource(); - var data = this.getInitialData(newSeriesOption, ecModel); - wrapData(data, this); - this.dataTask.dirty(); - this.dataTask.context.data = data; - inner$8(this).dataBeforeProcessed = data; - autoSeriesName(this); - - this._initSelectedMapFromData(data); - }; - - SeriesModel.prototype.fillDataTextStyle = function (data) { - // Default data label emphasis `show` - // FIXME Tree structure data ? - // FIXME Performance ? - if (data && !isTypedArray(data)) { - var props = ['show']; - - for (var i = 0; i < data.length; i++) { - if (data[i] && data[i].label) { - defaultEmphasis(data[i], 'label', props); - } - } - } - }; - /** - * Init a data structure from data related option in series - * Must be overridden. - */ - - - SeriesModel.prototype.getInitialData = function (option, ecModel) { - return; - }; - /** - * Append data to list - */ - - - SeriesModel.prototype.appendData = function (params) { - // FIXME ??? - // (1) If data from dataset, forbidden append. - // (2) support append data of dataset. - var data = this.getRawData(); - data.appendData(params.data); - }; - /** - * Consider some method like `filter`, `map` need make new data, - * We should make sure that `seriesModel.getData()` get correct - * data in the stream procedure. So we fetch data from upstream - * each time `task.perform` called. - */ - - - SeriesModel.prototype.getData = function (dataType) { - var task = getCurrentTask(this); - - if (task) { - var data = task.context.data; - return dataType == null ? data : data.getLinkedData(dataType); - } else { - // When series is not alive (that may happen when click toolbox - // restore or setOption with not merge mode), series data may - // be still need to judge animation or something when graphic - // elements want to know whether fade out. - return inner$8(this).data; - } - }; - - SeriesModel.prototype.getAllData = function () { - var mainData = this.getData(); - return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{ - data: mainData - }]; - }; - - SeriesModel.prototype.setData = function (data) { - var task = getCurrentTask(this); - - if (task) { - var context = task.context; // Consider case: filter, data sample. - // FIXME:TS never used, so comment it - // if (context.data !== data && task.modifyOutputEnd) { - // task.setOutputEnd(data.count()); - // } - - context.outputData = data; // Caution: setData should update context.data, - // Because getData may be called multiply in a - // single stage and expect to get the data just - // set. (For example, AxisProxy, x y both call - // getData and setDate sequentially). - // So the context.data should be fetched from - // upstream each time when a stage starts to be - // performed. - - if (task !== this.dataTask) { - context.data = data; - } - } - - inner$8(this).data = data; - }; - - SeriesModel.prototype.getEncode = function () { - var encode = this.get('encode', true); - - if (encode) { - return createHashMap(encode); - } - }; - - SeriesModel.prototype.getSourceManager = function () { - return inner$8(this).sourceManager; - }; - - SeriesModel.prototype.getSource = function () { - return this.getSourceManager().getSource(); - }; - /** - * Get data before processed - */ - - - SeriesModel.prototype.getRawData = function () { - return inner$8(this).dataBeforeProcessed; - }; - - SeriesModel.prototype.getColorBy = function () { - var colorBy = this.get('colorBy'); - return colorBy || 'series'; - }; - - SeriesModel.prototype.isColorBySeries = function () { - return this.getColorBy() === 'series'; - }; - /** - * Get base axis if has coordinate system and has axis. - * By default use coordSys.getBaseAxis(); - * Can be overridden for some chart. - * @return {type} description - */ - - - SeriesModel.prototype.getBaseAxis = function () { - var coordSys = this.coordinateSystem; // @ts-ignore - - return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); - }; - /** - * Default tooltip formatter - * - * @param dataIndex - * @param multipleSeries - * @param dataType - * @param renderMode valid values: 'html'(by default) and 'richText'. - * 'html' is used for rendering tooltip in extra DOM form, and the result - * string is used as DOM HTML content. - * 'richText' is used for rendering tooltip in rich text form, for those where - * DOM operation is not supported. - * @return formatted tooltip with `html` and `markers` - * Notice: The override method can also return string - */ - - - SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { - return defaultSeriesFormatTooltip({ - series: this, - dataIndex: dataIndex, - multipleSeries: multipleSeries - }); - }; - - SeriesModel.prototype.isAnimationEnabled = function () { - var ecModel = this.ecModel; // Disable animation if using echarts in node but not give ssr flag. - // In ssr mode, renderToString will generate svg with css animation. - - if (env.node && !(ecModel && ecModel.ssr)) { - return false; - } - - var animationEnabled = this.getShallow('animation'); - - if (animationEnabled) { - if (this.getData().count() > this.getShallow('animationThreshold')) { - animationEnabled = false; - } - } - - return !!animationEnabled; - }; - - SeriesModel.prototype.restoreData = function () { - this.dataTask.dirty(); - }; - - SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) { - var ecModel = this.ecModel; // PENDING - - var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum); - - if (!color) { - color = ecModel.getColorFromPalette(name, scope, requestColorNum); - } - - return color; - }; - /** - * Use `data.mapDimensionsAll(coordDim)` instead. - * @deprecated - */ - - - SeriesModel.prototype.coordDimToDataDim = function (coordDim) { - return this.getRawData().mapDimensionsAll(coordDim); - }; - /** - * Get progressive rendering count each step - */ - - - SeriesModel.prototype.getProgressive = function () { - return this.get('progressive'); - }; - /** - * Get progressive rendering count each step - */ - - - SeriesModel.prototype.getProgressiveThreshold = function () { - return this.get('progressiveThreshold'); - }; // PENGING If selectedMode is null ? - - - SeriesModel.prototype.select = function (innerDataIndices, dataType) { - this._innerSelect(this.getData(dataType), innerDataIndices); - }; - - SeriesModel.prototype.unselect = function (innerDataIndices, dataType) { - var selectedMap = this.option.selectedMap; - - if (!selectedMap) { - return; - } - - var selectedMode = this.option.selectedMode; - var data = this.getData(dataType); - - if (selectedMode === 'series' || selectedMap === 'all') { - this.option.selectedMap = {}; - this._selectedDataIndicesMap = {}; - return; - } - - for (var i = 0; i < innerDataIndices.length; i++) { - var dataIndex = innerDataIndices[i]; - var nameOrId = getSelectionKey(data, dataIndex); - selectedMap[nameOrId] = false; - this._selectedDataIndicesMap[nameOrId] = -1; - } - }; - - SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) { - var tmpArr = []; - - for (var i = 0; i < innerDataIndices.length; i++) { - tmpArr[0] = innerDataIndices[i]; - this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType); - } - }; - - SeriesModel.prototype.getSelectedDataIndices = function () { - if (this.option.selectedMap === 'all') { - return [].slice.call(this.getData().getIndices()); - } - - var selectedDataIndicesMap = this._selectedDataIndicesMap; - var nameOrIds = keys(selectedDataIndicesMap); - var dataIndices = []; - - for (var i = 0; i < nameOrIds.length; i++) { - var dataIndex = selectedDataIndicesMap[nameOrIds[i]]; - - if (dataIndex >= 0) { - dataIndices.push(dataIndex); - } - } - - return dataIndices; - }; - - SeriesModel.prototype.isSelected = function (dataIndex, dataType) { - var selectedMap = this.option.selectedMap; - - if (!selectedMap) { - return false; - } - - var data = this.getData(dataType); - return (selectedMap === 'all' || selectedMap[getSelectionKey(data, dataIndex)]) && !data.getItemModel(dataIndex).get(['select', 'disabled']); - }; - - SeriesModel.prototype.isUniversalTransitionEnabled = function () { - if (this[SERIES_UNIVERSAL_TRANSITION_PROP]) { - return true; - } - - var universalTransitionOpt = this.option.universalTransition; // Quick reject - - if (!universalTransitionOpt) { - return false; - } - - if (universalTransitionOpt === true) { - return true; - } // Can be simply 'universalTransition: true' - - - return universalTransitionOpt && universalTransitionOpt.enabled; - }; - - SeriesModel.prototype._innerSelect = function (data, innerDataIndices) { - var _a, _b; - - var option = this.option; - var selectedMode = option.selectedMode; - var len = innerDataIndices.length; - - if (!selectedMode || !len) { - return; - } - - if (selectedMode === 'series') { - option.selectedMap = 'all'; - } else if (selectedMode === 'multiple') { - if (!isObject$2(option.selectedMap)) { - option.selectedMap = {}; - } - - var selectedMap = option.selectedMap; - - for (var i = 0; i < len; i++) { - var dataIndex = innerDataIndices[i]; // TODO different types of data share same object. - - var nameOrId = getSelectionKey(data, dataIndex); - selectedMap[nameOrId] = true; - this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex); - } - } else if (selectedMode === 'single' || selectedMode === true) { - var lastDataIndex = innerDataIndices[len - 1]; - var nameOrId = getSelectionKey(data, lastDataIndex); - option.selectedMap = (_a = {}, _a[nameOrId] = true, _a); - this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b); - } - }; - - SeriesModel.prototype._initSelectedMapFromData = function (data) { - // Ignore select info in data if selectedMap exists. - // NOTE It's only for legacy usage. edge data is not supported. - if (this.option.selectedMap) { - return; - } - - var dataIndices = []; - - if (data.hasItemOption) { - data.each(function (idx) { - var rawItem = data.getRawDataItem(idx); - - if (rawItem && rawItem.selected) { - dataIndices.push(idx); - } - }); - } - - if (dataIndices.length > 0) { - this._innerSelect(data, dataIndices); - } - }; // /** - // * @see {module:echarts/stream/Scheduler} - // */ - // abstract pipeTask: null - - - SeriesModel.registerClass = function (clz) { - return ComponentModel.registerClass(clz); - }; - - SeriesModel.protoInitialize = function () { - var proto = SeriesModel.prototype; - proto.type = 'series.__base__'; - proto.seriesIndex = 0; - proto.ignoreStyleOnData = false; - proto.hasSymbolVisual = false; - proto.defaultSymbol = 'circle'; // Make sure the values can be accessed! - - proto.visualStyleAccessPath = 'itemStyle'; - proto.visualDrawType = 'fill'; - }(); - - return SeriesModel; - }(ComponentModel); - - mixin(SeriesModel, DataFormatMixin); - mixin(SeriesModel, PaletteMixin); - mountExtend(SeriesModel, ComponentModel); - /** - * MUST be called after `prepareSource` called - * Here we need to make auto series, especially for auto legend. But we - * do not modify series.name in option to avoid side effects. - */ - - function autoSeriesName(seriesModel) { - // User specified name has higher priority, otherwise it may cause - // series can not be queried unexpectedly. - var name = seriesModel.name; - - if (!isNameSpecified(seriesModel)) { - seriesModel.name = getSeriesAutoName(seriesModel) || name; - } - } - - function getSeriesAutoName(seriesModel) { - var data = seriesModel.getRawData(); - var dataDims = data.mapDimensionsAll('seriesName'); - var nameArr = []; - each$4(dataDims, function (dataDim) { - var dimInfo = data.getDimensionInfo(dataDim); - dimInfo.displayName && nameArr.push(dimInfo.displayName); - }); - return nameArr.join(' '); - } - - function dataTaskCount(context) { - return context.model.getRawData().count(); - } - - function dataTaskReset(context) { - var seriesModel = context.model; - seriesModel.setData(seriesModel.getRawData().cloneShallow()); - return dataTaskProgress; - } - - function dataTaskProgress(param, context) { - // Avoid repeat cloneShallow when data just created in reset. - if (context.outputData && param.end > context.outputData.count()) { - context.model.getRawData().cloneShallow(context.outputData); - } - } // TODO refactor - - - function wrapData(data, seriesModel) { - each$4(concatArray(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) { - data.wrapMethod(methodName, curry$1(onDataChange, seriesModel)); - }); - } - - function onDataChange(seriesModel, newList) { - var task = getCurrentTask(seriesModel); - - if (task) { - // Consider case: filter, selectRange - task.setOutputEnd((newList || this).count()); - } - - return newList; - } - - function getCurrentTask(seriesModel) { - var scheduler = (seriesModel.ecModel || {}).scheduler; - var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid); - - if (pipeline) { - // When pipline finished, the currrentTask keep the last - // task (renderTask). - var task = pipeline.currentTask; - - if (task) { - var agentStubMap = task.agentStubMap; - - if (agentStubMap) { - task = agentStubMap.get(seriesModel.uid); - } - } - - return task; - } - } - - var ComponentView = - /** @class */ - function () { - function ComponentView() { - this.group = new Group$2(); - this.uid = getUID('viewComponent'); - } - - ComponentView.prototype.init = function (ecModel, api) {}; - - ComponentView.prototype.render = function (model, ecModel, api, payload) {}; - - ComponentView.prototype.dispose = function (ecModel, api) {}; - - ComponentView.prototype.updateView = function (model, ecModel, api, payload) {// Do nothing; - }; - - ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {// Do nothing; - }; - - ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {// Do nothing; - }; - /** - * Hook for toggle blur target series. - * Can be used in marker for blur or leave blur the markers - */ - - - ComponentView.prototype.toggleBlurSeries = function (seriesModels, isBlur, ecModel) {// Do nothing; - }; - /** - * Traverse the new rendered elements. - * - * It will traverse the new added element in progressive rendering. - * And traverse all in normal rendering. - */ - - - ComponentView.prototype.eachRendered = function (cb) { - var group = this.group; - - if (group) { - group.traverse(cb); - } - }; - - return ComponentView; - }(); - - enableClassExtend(ComponentView); - enableClassManagement(ComponentView); - /** - * @return {string} If large mode changed, return string 'reset'; - */ - - function createRenderPlanner() { - var inner = makeInner(); - return function (seriesModel) { - var fields = inner(seriesModel); - var pipelineContext = seriesModel.pipelineContext; - var originalLarge = !!fields.large; - var originalProgressive = !!fields.progressiveRender; // FIXME: if the planner works on a filtered series, `pipelineContext` does not - // exists. See #11611 . Probably we need to modify this structure, see the comment - // on `performRawSeries` in `Schedular.js`. - - var large = fields.large = !!(pipelineContext && pipelineContext.large); - var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender); - return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset'; - }; - } - - var inner$7 = makeInner(); - var renderPlanner = createRenderPlanner(); - - var ChartView = - /** @class */ - function () { - function ChartView() { - this.group = new Group$2(); - this.uid = getUID('viewChart'); - this.renderTask = createTask({ - plan: renderTaskPlan, - reset: renderTaskReset - }); - this.renderTask.context = { - view: this - }; - } - - ChartView.prototype.init = function (ecModel, api) {}; - - ChartView.prototype.render = function (seriesModel, ecModel, api, payload) { - { - throw new Error('render method must been implemented'); - } - }; - /** - * Highlight series or specified data item. - */ - - - ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) { - var data = seriesModel.getData(payload && payload.dataType); - - if (!data) { - { - error("Unknown dataType " + payload.dataType); - } - return; - } - - toggleHighlight(data, payload, 'emphasis'); - }; - /** - * Downplay series or specified data item. - */ - - - ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) { - var data = seriesModel.getData(payload && payload.dataType); - - if (!data) { - { - error("Unknown dataType " + payload.dataType); - } - return; - } - - toggleHighlight(data, payload, 'normal'); - }; - /** - * Remove self. - */ - - - ChartView.prototype.remove = function (ecModel, api) { - this.group.removeAll(); - }; - /** - * Dispose self. - */ - - - ChartView.prototype.dispose = function (ecModel, api) {}; - - ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) { - this.render(seriesModel, ecModel, api, payload); - }; // FIXME never used? - - - ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) { - this.render(seriesModel, ecModel, api, payload); - }; // FIXME never used? - - - ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) { - this.render(seriesModel, ecModel, api, payload); - }; - /** - * Traverse the new rendered elements. - * - * It will traverse the new added element in progressive rendering. - * And traverse all in normal rendering. - */ - - - ChartView.prototype.eachRendered = function (cb) { - traverseElements(this.group, cb); - }; - - ChartView.markUpdateMethod = function (payload, methodName) { - inner$7(payload).updateMethod = methodName; - }; - - ChartView.protoInitialize = function () { - var proto = ChartView.prototype; - proto.type = 'chart'; - }(); - - return ChartView; - }(); - /** - * Set state of single element - */ - - - function elSetState(el, state, highlightDigit) { - if (el && isHighDownDispatcher(el)) { - (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit); - } - } - - function toggleHighlight(data, payload, state) { - var dataIndex = queryDataIndex(data, payload); - var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null; - - if (dataIndex != null) { - each$4(normalizeToArray(dataIndex), function (dataIdx) { - elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit); - }); - } else { - data.eachItemGraphicEl(function (el) { - elSetState(el, state, highlightDigit); - }); - } - } - - enableClassExtend(ChartView, ['dispose']); - enableClassManagement(ChartView); - - function renderTaskPlan(context) { - return renderPlanner(context.model); - } - - function renderTaskReset(context) { - var seriesModel = context.model; - var ecModel = context.ecModel; - var api = context.api; - var payload = context.payload; // FIXME: remove updateView updateVisual - - var progressiveRender = seriesModel.pipelineContext.progressiveRender; - var view = context.view; - var updateMethod = payload && inner$7(payload).updateMethod; - var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod // `appendData` is also supported when data amount - // is less than progressive threshold. - : 'render'; - - if (methodName !== 'render') { - view[methodName](seriesModel, ecModel, api, payload); - } - - return progressMethodMap[methodName]; - } - - var progressMethodMap = { - incrementalPrepareRender: { - progress: function (params, context) { - context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload); - } - }, - render: { - // Put view.render in `progress` to support appendData. But in this case - // view.render should not be called in reset, otherwise it will be called - // twise. Use `forceFirstProgress` to make sure that view.render is called - // in any cases. - forceFirstProgress: true, - progress: function (params, context) { - context.view.render(context.model, context.ecModel, context.api, context.payload); - } - } - }; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var ORIGIN_METHOD = '\0__throttleOriginMethod'; - var RATE = '\0__throttleRate'; - var THROTTLE_TYPE = '\0__throttleType'; - /** - * @public - * @param {(Function)} fn - * @param {number} [delay=0] Unit: ms. - * @param {boolean} [debounce=false] - * true: If call interval less than `delay`, only the last call works. - * false: If call interval less than `delay, call works on fixed rate. - * @return {(Function)} throttled fn. - */ - - function throttle(fn, delay, debounce) { - var currCall; - var lastCall = 0; - var lastExec = 0; - var timer = null; - var diff; - var scope; - var args; - var debounceNextCall; - delay = delay || 0; - - function exec() { - lastExec = new Date().getTime(); - timer = null; - fn.apply(scope, args || []); - } - - var cb = function () { - var cbArgs = []; - - for (var _i = 0; _i < arguments.length; _i++) { - cbArgs[_i] = arguments[_i]; - } - - currCall = new Date().getTime(); - scope = this; - args = cbArgs; - var thisDelay = debounceNextCall || delay; - var thisDebounce = debounceNextCall || debounce; - debounceNextCall = null; - diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay; - clearTimeout(timer); // Here we should make sure that: the `exec` SHOULD NOT be called later - // than a new call of `cb`, that is, preserving the command order. Consider - // calculating "scale rate" when roaming as an example. When a call of `cb` - // happens, either the `exec` is called dierectly, or the call is delayed. - // But the delayed call should never be later than next call of `cb`. Under - // this assurance, we can simply update view state each time `dispatchAction` - // triggered by user roaming, but not need to add extra code to avoid the - // state being "rolled-back". - - if (thisDebounce) { - timer = setTimeout(exec, thisDelay); - } else { - if (diff >= 0) { - exec(); - } else { - timer = setTimeout(exec, -diff); - } - } - - lastCall = currCall; - }; - /** - * Clear throttle. - * @public - */ - - - cb.clear = function () { - if (timer) { - clearTimeout(timer); - timer = null; - } - }; - /** - * Enable debounce once. - */ - - - cb.debounceNextCall = function (debounceDelay) { - debounceNextCall = debounceDelay; - }; - - return cb; - } - /** - * Create throttle method or update throttle rate. - * - * @example - * ComponentView.prototype.render = function () { - * ... - * throttle.createOrUpdate( - * this, - * '_dispatchAction', - * this.model.get('throttle'), - * 'fixRate' - * ); - * }; - * ComponentView.prototype.remove = function () { - * throttle.clear(this, '_dispatchAction'); - * }; - * ComponentView.prototype.dispose = function () { - * throttle.clear(this, '_dispatchAction'); - * }; - * - */ - - - function createOrUpdate(obj, fnAttr, rate, throttleType) { - var fn = obj[fnAttr]; - - if (!fn) { - return; - } - - var originFn = fn[ORIGIN_METHOD] || fn; - var lastThrottleType = fn[THROTTLE_TYPE]; - var lastRate = fn[RATE]; - - if (lastRate !== rate || lastThrottleType !== throttleType) { - if (rate == null || !throttleType) { - return obj[fnAttr] = originFn; - } - - fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce'); - fn[ORIGIN_METHOD] = originFn; - fn[THROTTLE_TYPE] = throttleType; - fn[RATE] = rate; - } - - return fn; - } - /** - * Clear throttle. Example see throttle.createOrUpdate. - */ - - - function clear(obj, fnAttr) { - var fn = obj[fnAttr]; - - if (fn && fn[ORIGIN_METHOD]) { - // Clear throttle - fn.clear && fn.clear(); - obj[fnAttr] = fn[ORIGIN_METHOD]; - } - } - - var inner$6 = makeInner(); - var defaultStyleMappers = { - itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true), - lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true) - }; - var defaultColorKey = { - lineStyle: 'stroke', - itemStyle: 'fill' - }; - - function getStyleMapper(seriesModel, stylePath) { - var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath]; - - if (!styleMapper) { - console.warn("Unknown style type '" + stylePath + "'."); - return defaultStyleMappers.itemStyle; - } - - return styleMapper; - } - - function getDefaultColorKey(seriesModel, stylePath) { - // return defaultColorKey[stylePath] || - var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath]; - - if (!colorKey) { - console.warn("Unknown style type '" + stylePath + "'."); - return 'fill'; - } - - return colorKey; - } - - var seriesStyleTask = { - createOnAllSeries: true, - performRawSeries: true, - reset: function (seriesModel, ecModel) { - var data = seriesModel.getData(); - var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle - - var styleModel = seriesModel.getModel(stylePath); - var getStyle = getStyleMapper(seriesModel, stylePath); - var globalStyle = getStyle(styleModel); - var decalOption = styleModel.getShallow('decal'); - - if (decalOption) { - data.setVisual('decal', decalOption); - decalOption.dirty = true; - } // TODO - - - var colorKey = getDefaultColorKey(seriesModel, stylePath); - var color = globalStyle[colorKey]; // TODO style callback - - var colorCallback = isFunction(color) ? color : null; - var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default. - - if (!globalStyle[colorKey] || colorCallback || hasAutoColor) { - // Note: If some series has color specified (e.g., by itemStyle.color), we DO NOT - // make it effect palette. Because some scenarios users need to make some series - // transparent or as background, which should better not effect the palette. - var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed. - seriesModel.name, null, ecModel.getSeriesCount()); - - if (!globalStyle[colorKey]) { - globalStyle[colorKey] = colorPalette; - data.setVisual('colorFromPalette', true); - } - - globalStyle.fill = globalStyle.fill === 'auto' || isFunction(globalStyle.fill) ? colorPalette : globalStyle.fill; - globalStyle.stroke = globalStyle.stroke === 'auto' || isFunction(globalStyle.stroke) ? colorPalette : globalStyle.stroke; - } - - data.setVisual('style', globalStyle); - data.setVisual('drawType', colorKey); // Only visible series has each data be visual encoded - - if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) { - data.setVisual('colorFromPalette', false); - return { - dataEach: function (data, idx) { - var dataParams = seriesModel.getDataParams(idx); - var itemStyle = extend({}, globalStyle); - itemStyle[colorKey] = colorCallback(dataParams); - data.setItemVisual(idx, 'style', itemStyle); - } - }; - } - } - }; - var sharedModel = new Model(); - var dataStyleTask = { - createOnAllSeries: true, - performRawSeries: true, - reset: function (seriesModel, ecModel) { - if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) { - return; - } - - var data = seriesModel.getData(); - var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle - - var getStyle = getStyleMapper(seriesModel, stylePath); - var colorKey = data.getVisual('drawType'); - return { - dataEach: data.hasItemOption ? function (data, idx) { - // Not use getItemModel for performance considuration - var rawItem = data.getRawDataItem(idx); - - if (rawItem && rawItem[stylePath]) { - sharedModel.option = rawItem[stylePath]; - var style = getStyle(sharedModel); - var existsStyle = data.ensureUniqueItemVisual(idx, 'style'); - extend(existsStyle, style); - - if (sharedModel.option.decal) { - data.setItemVisual(idx, 'decal', sharedModel.option.decal); - sharedModel.option.decal.dirty = true; - } - - if (colorKey in style) { - data.setItemVisual(idx, 'colorFromPalette', false); - } - } - } : null - }; - } - }; // Pick color from palette for the data which has not been set with color yet. - // Note: do not support stream rendering. No such cases yet. - - var dataColorPaletteTask = { - performRawSeries: true, - overallReset: function (ecModel) { - // Each type of series uses one scope. - // Pie and funnel are using different scopes. - var paletteScopeGroupByType = createHashMap(); - ecModel.eachSeries(function (seriesModel) { - var colorBy = seriesModel.getColorBy(); - - if (seriesModel.isColorBySeries()) { - return; - } - - var key = seriesModel.type + '-' + colorBy; - var colorScope = paletteScopeGroupByType.get(key); - - if (!colorScope) { - colorScope = {}; - paletteScopeGroupByType.set(key, colorScope); - } - - inner$6(seriesModel).scope = colorScope; - }); - ecModel.eachSeries(function (seriesModel) { - if (seriesModel.isColorBySeries() || ecModel.isSeriesFiltered(seriesModel)) { - return; - } - - var dataAll = seriesModel.getRawData(); - var idxMap = {}; - var data = seriesModel.getData(); - var colorScope = inner$6(seriesModel).scope; - var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; - var colorKey = getDefaultColorKey(seriesModel, stylePath); - data.each(function (idx) { - var rawIdx = data.getRawIndex(idx); - idxMap[rawIdx] = idx; - }); // Iterate on data before filtered. To make sure color from palette can be - // Consistent when toggling legend. - - dataAll.each(function (rawIdx) { - var idx = idxMap[rawIdx]; - var fromPalette = data.getItemVisual(idx, 'colorFromPalette'); // Get color from palette for each data only when the color is inherited from series color, which is - // also picked from color palette. So following situation is not in the case: - // 1. series.itemStyle.color is set - // 2. color is encoded by visualMap - - if (fromPalette) { - var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); - var name_1 = dataAll.getName(rawIdx) || rawIdx + ''; - var dataCount = dataAll.count(); - itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount); - } - }); - }); - } - }; - var PI$2 = Math.PI; - /** - * @param {module:echarts/ExtensionAPI} api - * @param {Object} [opts] - * @param {string} [opts.text] - * @param {string} [opts.color] - * @param {string} [opts.textColor] - * @return {module:zrender/Element} - */ - - function defaultLoading(api, opts) { - opts = opts || {}; - defaults(opts, { - text: 'loading', - textColor: '#000', - fontSize: 12, - fontWeight: 'normal', - fontStyle: 'normal', - fontFamily: 'sans-serif', - maskColor: 'rgba(255, 255, 255, 0.8)', - showSpinner: true, - color: '#5470c6', - spinnerRadius: 10, - lineWidth: 5, - zlevel: 0 - }); - var group = new Group$2(); - var mask = new Rect({ - style: { - fill: opts.maskColor - }, - zlevel: opts.zlevel, - z: 10000 - }); - group.add(mask); - var textContent = new ZRText({ - style: { - text: opts.text, - fill: opts.textColor, - fontSize: opts.fontSize, - fontWeight: opts.fontWeight, - fontStyle: opts.fontStyle, - fontFamily: opts.fontFamily - }, - zlevel: opts.zlevel, - z: 10001 - }); - var labelRect = new Rect({ - style: { - fill: 'none' - }, - textContent: textContent, - textConfig: { - position: 'right', - distance: 10 - }, - zlevel: opts.zlevel, - z: 10001 - }); - group.add(labelRect); - var arc; - - if (opts.showSpinner) { - arc = new Arc({ - shape: { - startAngle: -PI$2 / 2, - endAngle: -PI$2 / 2 + 0.1, - r: opts.spinnerRadius - }, - style: { - stroke: opts.color, - lineCap: 'round', - lineWidth: opts.lineWidth - }, - zlevel: opts.zlevel, - z: 10001 - }); - arc.animateShape(true).when(1000, { - endAngle: PI$2 * 3 / 2 - }).start('circularInOut'); - arc.animateShape(true).when(1000, { - startAngle: PI$2 * 3 / 2 - }).delay(300).start('circularInOut'); - group.add(arc); - } // Inject resize - - - group.resize = function () { - var textWidth = textContent.getBoundingRect().width; - var r = opts.showSpinner ? opts.spinnerRadius : 0; // cx = (containerWidth - arcDiameter - textDistance - textWidth) / 2 - // textDistance needs to be calculated when both animation and text exist - - var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner && textWidth ? 0 : 5 + textWidth / 2) // only show the text - + (opts.showSpinner ? 0 : textWidth / 2) // only show the spinner - + (textWidth ? 0 : r); - var cy = api.getHeight() / 2; - opts.showSpinner && arc.setShape({ - cx: cx, - cy: cy - }); - labelRect.setShape({ - x: cx - r, - y: cy - r, - width: r * 2, - height: r * 2 - }); - mask.setShape({ - x: 0, - y: 0, - width: api.getWidth(), - height: api.getHeight() - }); - }; - - group.resize(); - return group; - } - - var Scheduler = - /** @class */ - function () { - function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) { - // key: handlerUID - this._stageTaskMap = createHashMap(); - this.ecInstance = ecInstance; - this.api = api; // Fix current processors in case that in some rear cases that - // processors might be registered after echarts instance created. - // Register processors incrementally for a echarts instance is - // not supported by this stream architecture. - - dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice(); - visualHandlers = this._visualHandlers = visualHandlers.slice(); - this._allHandlers = dataProcessorHandlers.concat(visualHandlers); - } - - Scheduler.prototype.restoreData = function (ecModel, payload) { - // TODO: Only restore needed series and components, but not all components. - // Currently `restoreData` of all of the series and component will be called. - // But some independent components like `title`, `legend`, `graphic`, `toolbox`, - // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`, - // and some components like coordinate system, axes, dataZoom, visualMap only - // need their target series refresh. - // (1) If we are implementing this feature some day, we should consider these cases: - // if a data processor depends on a component (e.g., dataZoomProcessor depends - // on the settings of `dataZoom`), it should be re-performed if the component - // is modified by `setOption`. - // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`, - // it should be re-performed when the result array of `getTargetSeries` changed. - // We use `dependencies` to cover these issues. - // (3) How to update target series when coordinate system related components modified. - // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty, - // and this case all of the tasks will be set as dirty. - ecModel.restoreData(payload); // Theoretically an overall task not only depends on each of its target series, but also - // depends on all of the series. - // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks - // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure - // that the overall task is set as dirty and to be performed, otherwise it probably cause - // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it - // probably cause state chaos (consider `dataZoomProcessor`). - - this._stageTaskMap.each(function (taskRecord) { - var overallTask = taskRecord.overallTask; - overallTask && overallTask.dirty(); - }); - }; // If seriesModel provided, incremental threshold is check by series data. - - - Scheduler.prototype.getPerformArgs = function (task, isBlock) { - // For overall task - if (!task.__pipeline) { - return; - } - - var pipeline = this._pipelineMap.get(task.__pipeline.id); - - var pCtx = pipeline.context; - var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex; - var step = incremental ? pipeline.step : null; - var modDataCount = pCtx && pCtx.modDataCount; - var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null; - return { - step: step, - modBy: modBy, - modDataCount: modDataCount - }; - }; - - Scheduler.prototype.getPipeline = function (pipelineId) { - return this._pipelineMap.get(pipelineId); - }; - /** - * Current, progressive rendering starts from visual and layout. - * Always detect render mode in the same stage, avoiding that incorrect - * detection caused by data filtering. - * Caution: - * `updateStreamModes` use `seriesModel.getData()`. - */ - - - Scheduler.prototype.updateStreamModes = function (seriesModel, view) { - var pipeline = this._pipelineMap.get(seriesModel.uid); - - var data = seriesModel.getData(); - var dataLen = data.count(); // `progressiveRender` means that can render progressively in each - // animation frame. Note that some types of series do not provide - // `view.incrementalPrepareRender` but support `chart.appendData`. We - // use the term `incremental` but not `progressive` to describe the - // case that `chart.appendData`. - - var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold; - var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint. - // see `test/candlestick-large3.html` - - var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null; - seriesModel.pipelineContext = pipeline.context = { - progressiveRender: progressiveRender, - modDataCount: modDataCount, - large: large - }; - }; - - Scheduler.prototype.restorePipelines = function (ecModel) { - var scheduler = this; - var pipelineMap = scheduler._pipelineMap = createHashMap(); - ecModel.eachSeries(function (seriesModel) { - var progressive = seriesModel.getProgressive(); - var pipelineId = seriesModel.uid; - pipelineMap.set(pipelineId, { - id: pipelineId, - head: null, - tail: null, - threshold: seriesModel.getProgressiveThreshold(), - progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()), - blockIndex: -1, - step: Math.round(progressive || 700), - count: 0 - }); - - scheduler._pipe(seriesModel, seriesModel.dataTask); - }); - }; - - Scheduler.prototype.prepareStageTasks = function () { - var stageTaskMap = this._stageTaskMap; - var ecModel = this.api.getModel(); - var api = this.api; - each$4(this._allHandlers, function (handler) { - var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {}); - var errMsg = ''; - { - // Currently do not need to support to sepecify them both. - errMsg = '"reset" and "overallReset" must not be both specified.'; - } - assert(!(handler.reset && handler.overallReset), errMsg); - handler.reset && this._createSeriesStageTask(handler, record, ecModel, api); - handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api); - }, this); - }; - - Scheduler.prototype.prepareView = function (view, model, ecModel, api) { - var renderTask = view.renderTask; - var context = renderTask.context; - context.model = model; - context.ecModel = ecModel; - context.api = api; - renderTask.__block = !view.incrementalPrepareRender; - - this._pipe(model, renderTask); - }; - - Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) { - // If we do not use `block` here, it should be considered when to update modes. - this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, { - block: true - }); - }; - - Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) { - this._performStageTasks(this._visualHandlers, ecModel, payload, opt); - }; - - Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) { - opt = opt || {}; - var unfinished = false; - var scheduler = this; - each$4(stageHandlers, function (stageHandler, idx) { - if (opt.visualType && opt.visualType !== stageHandler.visualType) { - return; - } - - var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid); - - var seriesTaskMap = stageHandlerRecord.seriesTaskMap; - var overallTask = stageHandlerRecord.overallTask; - - if (overallTask) { - var overallNeedDirty_1; - var agentStubMap = overallTask.agentStubMap; - agentStubMap.each(function (stub) { - if (needSetDirty(opt, stub)) { - stub.dirty(); - overallNeedDirty_1 = true; - } - }); - overallNeedDirty_1 && overallTask.dirty(); - scheduler.updatePayload(overallTask, payload); - var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block); // Execute stubs firstly, which may set the overall task dirty, - // then execute the overall task. And stub will call seriesModel.setData, - // which ensures that in the overallTask seriesModel.getData() will not - // return incorrect data. - - agentStubMap.each(function (stub) { - stub.perform(performArgs_1); - }); - - if (overallTask.perform(performArgs_1)) { - unfinished = true; - } - } else if (seriesTaskMap) { - seriesTaskMap.each(function (task, pipelineId) { - if (needSetDirty(opt, task)) { - task.dirty(); - } - - var performArgs = scheduler.getPerformArgs(task, opt.block); // FIXME - // if intending to declare `performRawSeries` in handlers, only - // stream-independent (specifically, data item independent) operations can be - // performed. Because if a series is filtered, most of the tasks will not - // be performed. A stream-dependent operation probably cause wrong biz logic. - // Perhaps we should not provide a separate callback for this case instead - // of providing the config `performRawSeries`. The stream-dependent operations - // and stream-independent operations should better not be mixed. - - performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model); - scheduler.updatePayload(task, payload); - - if (task.perform(performArgs)) { - unfinished = true; - } - }); - } - }); - - function needSetDirty(opt, task) { - return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id)); - } - - this.unfinished = unfinished || this.unfinished; - }; - - Scheduler.prototype.performSeriesTasks = function (ecModel) { - var unfinished; - ecModel.eachSeries(function (seriesModel) { - // Progress to the end for dataInit and dataRestore. - unfinished = seriesModel.dataTask.perform() || unfinished; - }); - this.unfinished = unfinished || this.unfinished; - }; - - Scheduler.prototype.plan = function () { - // Travel pipelines, check block. - this._pipelineMap.each(function (pipeline) { - var task = pipeline.tail; - - do { - if (task.__block) { - pipeline.blockIndex = task.__idxInPipeline; - break; - } - - task = task.getUpstream(); - } while (task); - }); - }; - - Scheduler.prototype.updatePayload = function (task, payload) { - payload !== 'remain' && (task.context.payload = payload); - }; - - Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { - var scheduler = this; - var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap; // The count of stages are totally about only several dozen, so - // do not need to reuse the map. - - var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap(); - var seriesType = stageHandler.seriesType; - var getTargetSeries = stageHandler.getTargetSeries; // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily, - // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`, - // it works but it may cause other irrelevant charts blocked. - - if (stageHandler.createOnAllSeries) { - ecModel.eachRawSeries(create); - } else if (seriesType) { - ecModel.eachRawSeriesByType(seriesType, create); - } else if (getTargetSeries) { - getTargetSeries(ecModel, api).each(create); - } - - function create(seriesModel) { - var pipelineId = seriesModel.uid; // Init tasks for each seriesModel only once. - // Reuse original task instance. - - var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({ - plan: seriesTaskPlan, - reset: seriesTaskReset, - count: seriesTaskCount - })); - task.context = { - model: seriesModel, - ecModel: ecModel, - api: api, - // PENDING: `useClearVisual` not used? - useClearVisual: stageHandler.isVisual && !stageHandler.isLayout, - plan: stageHandler.plan, - reset: stageHandler.reset, - scheduler: scheduler - }; - - scheduler._pipe(seriesModel, task); - } - }; - - Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { - var scheduler = this; - var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask // For overall task, the function only be called on reset stage. - || createTask({ - reset: overallTaskReset - }); - overallTask.context = { - ecModel: ecModel, - api: api, - overallReset: stageHandler.overallReset, - scheduler: scheduler - }; - var oldAgentStubMap = overallTask.agentStubMap; // The count of stages are totally about only several dozen, so - // do not need to reuse the map. - - var newAgentStubMap = overallTask.agentStubMap = createHashMap(); - var seriesType = stageHandler.seriesType; - var getTargetSeries = stageHandler.getTargetSeries; - var overallProgress = true; - var shouldOverallTaskDirty = false; // FIXME:TS never used, so comment it - // let modifyOutputEnd = stageHandler.modifyOutputEnd; - // An overall task with seriesType detected or has `getTargetSeries`, we add - // stub in each pipelines, it will set the overall task dirty when the pipeline - // progress. Moreover, to avoid call the overall task each frame (too frequent), - // we set the pipeline block. - - var errMsg = ''; - { - errMsg = '"createOnAllSeries" is not supported for "overallReset", ' + 'because it will block all streams.'; - } - assert(!stageHandler.createOnAllSeries, errMsg); - - if (seriesType) { - ecModel.eachRawSeriesByType(seriesType, createStub); - } else if (getTargetSeries) { - getTargetSeries(ecModel, api).each(createStub); - } // Otherwise, (usually it is legacy case), the overall task will only be - // executed when upstream is dirty. Otherwise the progressive rendering of all - // pipelines will be disabled unexpectedly. But it still needs stubs to receive - // dirty info from upstream. - else { - overallProgress = false; - each$4(ecModel.getSeries(), createStub); - } - - function createStub(seriesModel) { - var pipelineId = seriesModel.uid; - var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || ( // When the result of `getTargetSeries` changed, the overallTask - // should be set as dirty and re-performed. - shouldOverallTaskDirty = true, createTask({ - reset: stubReset, - onDirty: stubOnDirty - }))); - stub.context = { - model: seriesModel, - overallProgress: overallProgress // FIXME:TS never used, so comment it - // modifyOutputEnd: modifyOutputEnd - - }; - stub.agent = overallTask; - stub.__block = overallProgress; - - scheduler._pipe(seriesModel, stub); - } - - if (shouldOverallTaskDirty) { - overallTask.dirty(); - } - }; - - Scheduler.prototype._pipe = function (seriesModel, task) { - var pipelineId = seriesModel.uid; - - var pipeline = this._pipelineMap.get(pipelineId); - - !pipeline.head && (pipeline.head = task); - pipeline.tail && pipeline.tail.pipe(task); - pipeline.tail = task; - task.__idxInPipeline = pipeline.count++; - task.__pipeline = pipeline; - }; - - Scheduler.wrapStageHandler = function (stageHandler, visualType) { - if (isFunction(stageHandler)) { - stageHandler = { - overallReset: stageHandler, - seriesType: detectSeriseType(stageHandler) - }; - } - - stageHandler.uid = getUID('stageHandler'); - visualType && (stageHandler.visualType = visualType); - return stageHandler; - }; - - return Scheduler; - }(); - - function overallTaskReset(context) { - context.overallReset(context.ecModel, context.api, context.payload); - } - - function stubReset(context) { - return context.overallProgress && stubProgress; - } - - function stubProgress() { - this.agent.dirty(); - this.getDownstream().dirty(); - } - - function stubOnDirty() { - this.agent && this.agent.dirty(); - } - - function seriesTaskPlan(context) { - return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null; - } - - function seriesTaskReset(context) { - if (context.useClearVisual) { - context.data.clearAllVisual(); - } - - var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload)); - return resetDefines.length > 1 ? map$1(resetDefines, function (v, idx) { - return makeSeriesTaskProgress(idx); - }) : singleSeriesTaskProgress; - } - - var singleSeriesTaskProgress = makeSeriesTaskProgress(0); - - function makeSeriesTaskProgress(resetDefineIdx) { - return function (params, context) { - var data = context.data; - var resetDefine = context.resetDefines[resetDefineIdx]; - - if (resetDefine && resetDefine.dataEach) { - for (var i = params.start; i < params.end; i++) { - resetDefine.dataEach(data, i); - } - } else if (resetDefine && resetDefine.progress) { - resetDefine.progress(params, data); - } - }; - } - - function seriesTaskCount(context) { - return context.data.count(); - } - /** - * Only some legacy stage handlers (usually in echarts extensions) are pure function. - * To ensure that they can work normally, they should work in block mode, that is, - * they should not be started util the previous tasks finished. So they cause the - * progressive rendering disabled. We try to detect the series type, to narrow down - * the block range to only the series type they concern, but not all series. - */ - - - function detectSeriseType(legacyFunc) { - seriesType = null; - - try { - // Assume there is no async when calling `eachSeriesByType`. - legacyFunc(ecModelMock, apiMock); - } catch (e) {} - - return seriesType; - } - - var ecModelMock = {}; - var apiMock = {}; - var seriesType; - mockMethods(ecModelMock, GlobalModel); - mockMethods(apiMock, ExtensionAPI); - - ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) { - seriesType = type; - }; - - ecModelMock.eachComponent = function (cond) { - if (cond.mainType === 'series' && cond.subType) { - seriesType = cond.subType; - } - }; - - function mockMethods(target, Clz) { - /* eslint-disable */ - for (var name_1 in Clz.prototype) { - // Do not use hasOwnProperty - target[name_1] = noop; - } - /* eslint-enable */ - - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF']; - var lightTheme = { - color: colorAll, - colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll] - }; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var contrastColor = '#B9B8CE'; - var backgroundColor = '#100C2A'; - - var axisCommon = function () { - return { - axisLine: { - lineStyle: { - color: contrastColor - } - }, - splitLine: { - lineStyle: { - color: '#484753' - } - }, - splitArea: { - areaStyle: { - color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)'] - } - }, - minorSplitLine: { - lineStyle: { - color: '#20203B' - } - } - }; - }; - - var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff']; - var theme = { - darkMode: true, - color: colorPalette, - backgroundColor: backgroundColor, - axisPointer: { - lineStyle: { - color: '#817f91' - }, - crossStyle: { - color: '#817f91' - }, - label: { - // TODO Contrast of label backgorundColor - color: '#fff' - } - }, - legend: { - textStyle: { - color: contrastColor - } - }, - textStyle: { - color: contrastColor - }, - title: { - textStyle: { - color: '#EEF1FA' - }, - subtextStyle: { - color: '#B9B8CE' - } - }, - toolbox: { - iconStyle: { - borderColor: contrastColor - } - }, - dataZoom: { - borderColor: '#71708A', - textStyle: { - color: contrastColor - }, - brushStyle: { - color: 'rgba(135,163,206,0.3)' - }, - handleStyle: { - color: '#353450', - borderColor: '#C5CBE3' - }, - moveHandleStyle: { - color: '#B0B6C3', - opacity: 0.3 - }, - fillerColor: 'rgba(135,163,206,0.2)', - emphasis: { - handleStyle: { - borderColor: '#91B7F2', - color: '#4D587D' - }, - moveHandleStyle: { - color: '#636D9A', - opacity: 0.7 - } - }, - dataBackground: { - lineStyle: { - color: '#71708A', - width: 1 - }, - areaStyle: { - color: '#71708A' - } - }, - selectedDataBackground: { - lineStyle: { - color: '#87A3CE' - }, - areaStyle: { - color: '#87A3CE' - } - } - }, - visualMap: { - textStyle: { - color: contrastColor - } - }, - timeline: { - lineStyle: { - color: contrastColor - }, - label: { - color: contrastColor - }, - controlStyle: { - color: contrastColor, - borderColor: contrastColor - } - }, - calendar: { - itemStyle: { - color: backgroundColor - }, - dayLabel: { - color: contrastColor - }, - monthLabel: { - color: contrastColor - }, - yearLabel: { - color: contrastColor - } - }, - timeAxis: axisCommon(), - logAxis: axisCommon(), - valueAxis: axisCommon(), - categoryAxis: axisCommon(), - line: { - symbol: 'circle' - }, - graph: { - color: colorPalette - }, - gauge: { - title: { - color: contrastColor - }, - axisLine: { - lineStyle: { - color: [[1, 'rgba(207,212,219,0.2)']] - } - }, - axisLabel: { - color: contrastColor - }, - detail: { - color: '#EEF1FA' - } - }, - candlestick: { - itemStyle: { - color: '#f64e56', - color0: '#54ea92', - borderColor: '#f64e56', - borderColor0: '#54ea92' // borderColor: '#ca2824', - // borderColor0: '#09a443' - - } - } - }; - theme.categoryAxis.splitLine.show = false; - /** - * Usage of query: - * `chart.on('click', query, handler);` - * The `query` can be: - * + The component type query string, only `mainType` or `mainType.subType`, - * like: 'xAxis', 'series', 'xAxis.category' or 'series.line'. - * + The component query object, like: - * `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`, - * `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`. - * + The data query object, like: - * `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`. - * + The other query object (cmponent customized query), like: - * `{element: 'some'}` (only available in custom series). - * - * Caveat: If a prop in the `query` object is `null/undefined`, it is the - * same as there is no such prop in the `query` object. - */ - - var ECEventProcessor = - /** @class */ - function () { - function ECEventProcessor() {} - - ECEventProcessor.prototype.normalizeQuery = function (query) { - var cptQuery = {}; - var dataQuery = {}; - var otherQuery = {}; // `query` is `mainType` or `mainType.subType` of component. - - if (isString(query)) { - var condCptType = parseClassType(query); // `.main` and `.sub` may be ''. - - cptQuery.mainType = condCptType.main || null; - cptQuery.subType = condCptType.sub || null; - } // `query` is an object, convert to {mainType, index, name, id}. - else { - // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved, - // can not be used in `compomentModel.filterForExposedEvent`. - var suffixes_1 = ['Index', 'Name', 'Id']; - var dataKeys_1 = { - name: 1, - dataIndex: 1, - dataType: 1 - }; - each$4(query, function (val, key) { - var reserved = false; - - for (var i = 0; i < suffixes_1.length; i++) { - var propSuffix = suffixes_1[i]; - var suffixPos = key.lastIndexOf(propSuffix); - - if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) { - var mainType = key.slice(0, suffixPos); // Consider `dataIndex`. - - if (mainType !== 'data') { - cptQuery.mainType = mainType; - cptQuery[propSuffix.toLowerCase()] = val; - reserved = true; - } - } - } - - if (dataKeys_1.hasOwnProperty(key)) { - dataQuery[key] = val; - reserved = true; - } - - if (!reserved) { - otherQuery[key] = val; - } - }); - } - - return { - cptQuery: cptQuery, - dataQuery: dataQuery, - otherQuery: otherQuery - }; - }; - - ECEventProcessor.prototype.filter = function (eventType, query) { - // They should be assigned before each trigger call. - var eventInfo = this.eventInfo; - - if (!eventInfo) { - return true; - } - - var targetEl = eventInfo.targetEl; - var packedEvent = eventInfo.packedEvent; - var model = eventInfo.model; - var view = eventInfo.view; // For event like 'globalout'. - - if (!model || !view) { - return true; - } - - var cptQuery = query.cptQuery; - var dataQuery = query.dataQuery; - return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent)); - - function check(query, host, prop, propOnHost) { - return query[prop] == null || host[propOnHost || prop] === query[prop]; - } - }; - - ECEventProcessor.prototype.afterTrigger = function () { - // Make sure the eventInfo won't be used in next trigger. - this.eventInfo = null; - }; - - return ECEventProcessor; - }(); - - var SYMBOL_PROPS_WITH_CB = ['symbol', 'symbolSize', 'symbolRotate', 'symbolOffset']; - var SYMBOL_PROPS = SYMBOL_PROPS_WITH_CB.concat(['symbolKeepAspect']); // Encoding visual for all series include which is filtered for legend drawing - - var seriesSymbolTask = { - createOnAllSeries: true, - // For legend. - performRawSeries: true, - reset: function (seriesModel, ecModel) { - var data = seriesModel.getData(); - - if (seriesModel.legendIcon) { - data.setVisual('legendIcon', seriesModel.legendIcon); - } - - if (!seriesModel.hasSymbolVisual) { - return; - } - - var symbolOptions = {}; - var symbolOptionsCb = {}; - var hasCallback = false; - - for (var i = 0; i < SYMBOL_PROPS_WITH_CB.length; i++) { - var symbolPropName = SYMBOL_PROPS_WITH_CB[i]; - var val = seriesModel.get(symbolPropName); - - if (isFunction(val)) { - hasCallback = true; - symbolOptionsCb[symbolPropName] = val; - } else { - symbolOptions[symbolPropName] = val; - } - } - - symbolOptions.symbol = symbolOptions.symbol || seriesModel.defaultSymbol; - data.setVisual(extend({ - legendIcon: seriesModel.legendIcon || symbolOptions.symbol, - symbolKeepAspect: seriesModel.get('symbolKeepAspect') - }, symbolOptions)); // Only visible series has each data be visual encoded - - if (ecModel.isSeriesFiltered(seriesModel)) { - return; - } - - var symbolPropsCb = keys(symbolOptionsCb); - - function dataEach(data, idx) { - var rawValue = seriesModel.getRawValue(idx); - var params = seriesModel.getDataParams(idx); - - for (var i = 0; i < symbolPropsCb.length; i++) { - var symbolPropName = symbolPropsCb[i]; - data.setItemVisual(idx, symbolPropName, symbolOptionsCb[symbolPropName](rawValue, params)); - } - } - - return { - dataEach: hasCallback ? dataEach : null - }; - } - }; - var dataSymbolTask = { - createOnAllSeries: true, - // For legend. - performRawSeries: true, - reset: function (seriesModel, ecModel) { - if (!seriesModel.hasSymbolVisual) { - return; - } // Only visible series has each data be visual encoded - - - if (ecModel.isSeriesFiltered(seriesModel)) { - return; - } - - var data = seriesModel.getData(); - - function dataEach(data, idx) { - var itemModel = data.getItemModel(idx); - - for (var i = 0; i < SYMBOL_PROPS.length; i++) { - var symbolPropName = SYMBOL_PROPS[i]; - var val = itemModel.getShallow(symbolPropName, true); - - if (val != null) { - data.setItemVisual(idx, symbolPropName, val); - } - } - } - - return { - dataEach: data.hasItemOption ? dataEach : null - }; - } - }; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - function getItemVisualFromData(data, dataIndex, key) { - switch (key) { - case 'color': - var style = data.getItemVisual(dataIndex, 'style'); - return style[data.getVisual('drawType')]; - - case 'opacity': - return data.getItemVisual(dataIndex, 'style').opacity; - - case 'symbol': - case 'symbolSize': - case 'liftZ': - return data.getItemVisual(dataIndex, key); - - default: - { - console.warn("Unknown visual type " + key); - } - } - } - - function getVisualFromData(data, key) { - switch (key) { - case 'color': - var style = data.getVisual('style'); - return style[data.getVisual('drawType')]; - - case 'opacity': - return data.getVisual('style').opacity; - - case 'symbol': - case 'symbolSize': - case 'liftZ': - return data.getVisual(key); - - default: - { - console.warn("Unknown visual type " + key); - } - } - } // Legacy data selection action. - // Includes: pieSelect, pieUnSelect, pieToggleSelect, mapSelect, mapUnSelect, mapToggleSelect - - - function createLegacyDataSelectAction(seriesType, ecRegisterAction) { - function getSeriesIndices(ecModel, payload) { - var seriesIndices = []; - ecModel.eachComponent({ - mainType: 'series', - subType: seriesType, - query: payload - }, function (seriesModel) { - seriesIndices.push(seriesModel.seriesIndex); - }); - return seriesIndices; - } - - each$4([[seriesType + 'ToggleSelect', 'toggleSelect'], [seriesType + 'Select', 'select'], [seriesType + 'UnSelect', 'unselect']], function (eventsMap) { - ecRegisterAction(eventsMap[0], function (payload, ecModel, api) { - payload = extend({}, payload); - { - deprecateReplaceLog(payload.type, eventsMap[1]); - } - api.dispatchAction(extend(payload, { - type: eventsMap[1], - seriesIndex: getSeriesIndices(ecModel, payload) - })); - }); - }); - } - - function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) { - var legacyEventName = type + eventPostfix; - - if (!ecIns.isSilent(legacyEventName)) { - { - deprecateLog("event " + legacyEventName + " is deprecated."); - } - ecModel.eachComponent({ - mainType: 'series', - subType: 'pie' - }, function (seriesModel) { - var seriesIndex = seriesModel.seriesIndex; - var selectedMap = seriesModel.option.selectedMap; - var selected = payload.selected; - - for (var i = 0; i < selected.length; i++) { - if (selected[i].seriesIndex === seriesIndex) { - var data = seriesModel.getData(); - var dataIndex = queryDataIndex(data, payload.fromActionPayload); - ecIns.trigger(legacyEventName, { - type: legacyEventName, - seriesId: seriesModel.id, - name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex), - selected: isString(selectedMap) ? selectedMap : extend({}, selectedMap) - }); - } - } - }); - } - } - - function handleLegacySelectEvents(messageCenter, ecIns, api) { - messageCenter.on('selectchanged', function (params) { - var ecModel = api.getModel(); - - if (params.isFromClick) { - handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params); - handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params); - } else if (params.fromAction === 'select') { - handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params); - handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params); - } else if (params.fromAction === 'unselect') { - handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params); - handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params); - } - }); - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - function findEventDispatcher(target, det, returnFirstMatch) { - var found; - - while (target) { - if (det(target)) { - found = target; - - if (returnFirstMatch) { - break; - } - } - - target = target.__hostTarget || target.parent; - } - - return found; - } - - var wmUniqueIndex = Math.round(Math.random() * 9); - var supportDefineProperty = typeof Object.defineProperty === 'function'; - - var WeakMap = function () { - function WeakMap() { - this._id = '__ec_inner_' + wmUniqueIndex++; - } - - WeakMap.prototype.get = function (key) { - return this._guard(key)[this._id]; - }; - - WeakMap.prototype.set = function (key, value) { - var target = this._guard(key); - - if (supportDefineProperty) { - Object.defineProperty(target, this._id, { - value: value, - enumerable: false, - configurable: true - }); - } else { - target[this._id] = value; - } - - return this; - }; - - WeakMap.prototype["delete"] = function (key) { - if (this.has(key)) { - delete this._guard(key)[this._id]; - return true; - } - - return false; - }; - - WeakMap.prototype.has = function (key) { - return !!this._guard(key)[this._id]; - }; - - WeakMap.prototype._guard = function (key) { - if (key !== Object(key)) { - throw TypeError('Value of WeakMap is not a non-null object.'); - } - - return key; - }; - - return WeakMap; - }(); - /** - * Triangle shape - * @inner - */ - - - var Triangle = Path.extend({ - type: 'triangle', - shape: { - cx: 0, - cy: 0, - width: 0, - height: 0 - }, - buildPath: function (path, shape) { - var cx = shape.cx; - var cy = shape.cy; - var width = shape.width / 2; - var height = shape.height / 2; - path.moveTo(cx, cy - height); - path.lineTo(cx + width, cy + height); - path.lineTo(cx - width, cy + height); - path.closePath(); - } - }); - /** - * Diamond shape - * @inner - */ - - var Diamond = Path.extend({ - type: 'diamond', - shape: { - cx: 0, - cy: 0, - width: 0, - height: 0 - }, - buildPath: function (path, shape) { - var cx = shape.cx; - var cy = shape.cy; - var width = shape.width / 2; - var height = shape.height / 2; - path.moveTo(cx, cy - height); - path.lineTo(cx + width, cy); - path.lineTo(cx, cy + height); - path.lineTo(cx - width, cy); - path.closePath(); - } - }); - /** - * Pin shape - * @inner - */ - - var Pin = Path.extend({ - type: 'pin', - shape: { - // x, y on the cusp - x: 0, - y: 0, - width: 0, - height: 0 - }, - buildPath: function (path, shape) { - var x = shape.x; - var y = shape.y; - var w = shape.width / 5 * 3; // Height must be larger than width - - var h = Math.max(w, shape.height); - var r = w / 2; // Dist on y with tangent point and circle center - - var dy = r * r / (h - r); - var cy = y - h + r + dy; - var angle = Math.asin(dy / r); // Dist on x with tangent point and circle center - - var dx = Math.cos(angle) * r; - var tanX = Math.sin(angle); - var tanY = Math.cos(angle); - var cpLen = r * 0.6; - var cpLen2 = r * 0.7; - path.moveTo(x - dx, cy + dy); - path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle); - path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y); - path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy); - path.closePath(); - } - }); - /** - * Arrow shape - * @inner - */ - - var Arrow = Path.extend({ - type: 'arrow', - shape: { - x: 0, - y: 0, - width: 0, - height: 0 - }, - buildPath: function (ctx, shape) { - var height = shape.height; - var width = shape.width; - var x = shape.x; - var y = shape.y; - var dx = width / 3 * 2; - ctx.moveTo(x, y); - ctx.lineTo(x + dx, y + height); - ctx.lineTo(x, y + height / 4 * 3); - ctx.lineTo(x - dx, y + height); - ctx.lineTo(x, y); - ctx.closePath(); - } - }); - /** - * Map of path constructors - */ - // TODO Use function to build symbol path. - - var symbolCtors = { - line: Line, - rect: Rect, - roundRect: Rect, - square: Rect, - circle: Circle, - diamond: Diamond, - pin: Pin, - arrow: Arrow, - triangle: Triangle - }; - var symbolShapeMakers = { - line: function (x, y, w, h, shape) { - shape.x1 = x; - shape.y1 = y + h / 2; - shape.x2 = x + w; - shape.y2 = y + h / 2; - }, - rect: function (x, y, w, h, shape) { - shape.x = x; - shape.y = y; - shape.width = w; - shape.height = h; - }, - roundRect: function (x, y, w, h, shape) { - shape.x = x; - shape.y = y; - shape.width = w; - shape.height = h; - shape.r = Math.min(w, h) / 4; - }, - square: function (x, y, w, h, shape) { - var size = Math.min(w, h); - shape.x = x; - shape.y = y; - shape.width = size; - shape.height = size; - }, - circle: function (x, y, w, h, shape) { - // Put circle in the center of square - shape.cx = x + w / 2; - shape.cy = y + h / 2; - shape.r = Math.min(w, h) / 2; - }, - diamond: function (x, y, w, h, shape) { - shape.cx = x + w / 2; - shape.cy = y + h / 2; - shape.width = w; - shape.height = h; - }, - pin: function (x, y, w, h, shape) { - shape.x = x + w / 2; - shape.y = y + h / 2; - shape.width = w; - shape.height = h; - }, - arrow: function (x, y, w, h, shape) { - shape.x = x + w / 2; - shape.y = y + h / 2; - shape.width = w; - shape.height = h; - }, - triangle: function (x, y, w, h, shape) { - shape.cx = x + w / 2; - shape.cy = y + h / 2; - shape.width = w; - shape.height = h; - } - }; - var symbolBuildProxies = {}; - each$4(symbolCtors, function (Ctor, name) { - symbolBuildProxies[name] = new Ctor(); - }); - var SymbolClz = Path.extend({ - type: 'symbol', - shape: { - symbolType: '', - x: 0, - y: 0, - width: 0, - height: 0 - }, - calculateTextPosition: function (out, config, rect) { - var res = calculateTextPosition(out, config, rect); - var shape = this.shape; - - if (shape && shape.symbolType === 'pin' && config.position === 'inside') { - res.y = rect.y + rect.height * 0.4; - } - - return res; - }, - buildPath: function (ctx, shape, inBundle) { - var symbolType = shape.symbolType; - - if (symbolType !== 'none') { - var proxySymbol = symbolBuildProxies[symbolType]; - - if (!proxySymbol) { - // Default rect - symbolType = 'rect'; - proxySymbol = symbolBuildProxies[symbolType]; - } - - symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape); - proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle); - } - } - }); // Provide setColor helper method to avoid determine if set the fill or stroke outside - - function symbolPathSetColor(color, innerColor) { - if (this.type !== 'image') { - var symbolStyle = this.style; - - if (this.__isEmptyBrush) { - symbolStyle.stroke = color; - symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView - - symbolStyle.lineWidth = 2; - } else if (this.shape.symbolType === 'line') { - symbolStyle.stroke = color; - } else { - symbolStyle.fill = color; - } - - this.markRedraw(); - } - } - /** - * Create a symbol element with given symbol configuration: shape, x, y, width, height, color - */ - - - function createSymbol(symbolType, x, y, w, h, color, // whether to keep the ratio of w/h, - keepAspect) { - // TODO Support image object, DynamicImage. - var isEmpty = symbolType.indexOf('empty') === 0; - - if (isEmpty) { - symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6); - } - - var symbolPath; - - if (symbolType.indexOf('image://') === 0) { - symbolPath = makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); - } else if (symbolType.indexOf('path://') === 0) { - symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); - } else { - symbolPath = new SymbolClz({ - shape: { - symbolType: symbolType, - x: x, - y: y, - width: w, - height: h - } - }); - } - - symbolPath.__isEmptyBrush = isEmpty; // TODO Should deprecate setColor - - symbolPath.setColor = symbolPathSetColor; - - if (color) { - symbolPath.setColor(color); - } - - return symbolPath; - } - - function normalizeSymbolSize(symbolSize) { - if (!isArray(symbolSize)) { - symbolSize = [+symbolSize, +symbolSize]; - } - - return [symbolSize[0] || 0, symbolSize[1] || 0]; - } - - function normalizeSymbolOffset(symbolOffset, symbolSize) { - if (symbolOffset == null) { - return; - } - - if (!isArray(symbolOffset)) { - symbolOffset = [symbolOffset, symbolOffset]; - } - - return [parsePercent(symbolOffset[0], symbolSize[0]) || 0, parsePercent(retrieve2(symbolOffset[1], symbolOffset[0]), symbolSize[1]) || 0]; - } - - function isSafeNum(num) { - return isFinite(num); - } - - function createLinearGradient(ctx, obj, rect) { - var x = obj.x == null ? 0 : obj.x; - var x2 = obj.x2 == null ? 1 : obj.x2; - var y = obj.y == null ? 0 : obj.y; - var y2 = obj.y2 == null ? 0 : obj.y2; - - if (!obj.global) { - x = x * rect.width + rect.x; - x2 = x2 * rect.width + rect.x; - y = y * rect.height + rect.y; - y2 = y2 * rect.height + rect.y; - } - - x = isSafeNum(x) ? x : 0; - x2 = isSafeNum(x2) ? x2 : 1; - y = isSafeNum(y) ? y : 0; - y2 = isSafeNum(y2) ? y2 : 0; - var canvasGradient = ctx.createLinearGradient(x, y, x2, y2); - return canvasGradient; - } - - function createRadialGradient(ctx, obj, rect) { - var width = rect.width; - var height = rect.height; - var min = Math.min(width, height); - var x = obj.x == null ? 0.5 : obj.x; - var y = obj.y == null ? 0.5 : obj.y; - var r = obj.r == null ? 0.5 : obj.r; - - if (!obj.global) { - x = x * width + rect.x; - y = y * height + rect.y; - r = r * min; - } - - x = isSafeNum(x) ? x : 0.5; - y = isSafeNum(y) ? y : 0.5; - r = r >= 0 && isSafeNum(r) ? r : 0.5; - var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r); - return canvasGradient; - } - - function getCanvasGradient(ctx, obj, rect) { - var canvasGradient = obj.type === 'radial' ? createRadialGradient(ctx, obj, rect) : createLinearGradient(ctx, obj, rect); - var colorStops = obj.colorStops; - - for (var i = 0; i < colorStops.length; i++) { - canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color); - } - - return canvasGradient; - } - - function isClipPathChanged(clipPaths, prevClipPaths) { - if (clipPaths === prevClipPaths || !clipPaths && !prevClipPaths) { - return false; - } - - if (!clipPaths || !prevClipPaths || clipPaths.length !== prevClipPaths.length) { - return true; - } - - for (var i = 0; i < clipPaths.length; i++) { - if (clipPaths[i] !== prevClipPaths[i]) { - return true; - } - } - - return false; - } - - function parseInt10(val) { - return parseInt(val, 10); - } - - function getSize(root, whIdx, opts) { - var wh = ['width', 'height'][whIdx]; - var cwh = ['clientWidth', 'clientHeight'][whIdx]; - var plt = ['paddingLeft', 'paddingTop'][whIdx]; - var prb = ['paddingRight', 'paddingBottom'][whIdx]; - - if (opts[wh] != null && opts[wh] !== 'auto') { - return parseFloat(opts[wh]); - } - - var stl = document.defaultView.getComputedStyle(root); - return (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) - (parseInt10(stl[plt]) || 0) - (parseInt10(stl[prb]) || 0) | 0; - } - - function normalizeLineDash(lineType, lineWidth) { - if (!lineType || lineType === 'solid' || !(lineWidth > 0)) { - return null; - } - - return lineType === 'dashed' ? [4 * lineWidth, 2 * lineWidth] : lineType === 'dotted' ? [lineWidth] : isNumber(lineType) ? [lineType] : isArray(lineType) ? lineType : null; - } - - function getLineDash(el) { - var style = el.style; - var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); - var lineDashOffset = style.lineDashOffset; - - if (lineDash) { - var lineScale_1 = style.strokeNoScale && el.getLineScale ? el.getLineScale() : 1; - - if (lineScale_1 && lineScale_1 !== 1) { - lineDash = map$1(lineDash, function (rawVal) { - return rawVal / lineScale_1; - }); - lineDashOffset /= lineScale_1; - } - } - - return [lineDash, lineDashOffset]; - } - - var pathProxyForDraw = new PathProxy(true); - - function styleHasStroke(style) { - var stroke = style.stroke; - return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); - } - - function isValidStrokeFillStyle(strokeOrFill) { - return typeof strokeOrFill === 'string' && strokeOrFill !== 'none'; - } - - function styleHasFill(style) { - var fill = style.fill; - return fill != null && fill !== 'none'; - } - - function doFillPath(ctx, style) { - if (style.fillOpacity != null && style.fillOpacity !== 1) { - var originalGlobalAlpha = ctx.globalAlpha; - ctx.globalAlpha = style.fillOpacity * style.opacity; - ctx.fill(); - ctx.globalAlpha = originalGlobalAlpha; - } else { - ctx.fill(); - } - } - - function doStrokePath(ctx, style) { - if (style.strokeOpacity != null && style.strokeOpacity !== 1) { - var originalGlobalAlpha = ctx.globalAlpha; - ctx.globalAlpha = style.strokeOpacity * style.opacity; - ctx.stroke(); - ctx.globalAlpha = originalGlobalAlpha; - } else { - ctx.stroke(); - } - } - - function createCanvasPattern(ctx, pattern, el) { - var image = createOrUpdateImage(pattern.image, pattern.__image, el); - - if (isImageReady(image)) { - var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat'); - - if (typeof DOMMatrix === 'function' && canvasPattern && canvasPattern.setTransform) { - var matrix = new DOMMatrix(); - matrix.translateSelf(pattern.x || 0, pattern.y || 0); - matrix.rotateSelf(0, 0, (pattern.rotation || 0) * RADIAN_TO_DEGREE); - matrix.scaleSelf(pattern.scaleX || 1, pattern.scaleY || 1); - canvasPattern.setTransform(matrix); - } - - return canvasPattern; - } - } - - function brushPath(ctx, el, style, inBatch) { - var _a; - - var hasStroke = styleHasStroke(style); - var hasFill = styleHasFill(style); - var strokePercent = style.strokePercent; - var strokePart = strokePercent < 1; - var firstDraw = !el.path; - - if ((!el.silent || strokePart) && firstDraw) { - el.createPathProxy(); - } - - var path = el.path || pathProxyForDraw; - var dirtyFlag = el.__dirty; - - if (!inBatch) { - var fill = style.fill; - var stroke = style.stroke; - var hasFillGradient = hasFill && !!fill.colorStops; - var hasStrokeGradient = hasStroke && !!stroke.colorStops; - var hasFillPattern = hasFill && !!fill.image; - var hasStrokePattern = hasStroke && !!stroke.image; - var fillGradient = void 0; - var strokeGradient = void 0; - var fillPattern = void 0; - var strokePattern = void 0; - var rect = void 0; - - if (hasFillGradient || hasStrokeGradient) { - rect = el.getBoundingRect(); - } - - if (hasFillGradient) { - fillGradient = dirtyFlag ? getCanvasGradient(ctx, fill, rect) : el.__canvasFillGradient; - el.__canvasFillGradient = fillGradient; - } - - if (hasStrokeGradient) { - strokeGradient = dirtyFlag ? getCanvasGradient(ctx, stroke, rect) : el.__canvasStrokeGradient; - el.__canvasStrokeGradient = strokeGradient; - } - - if (hasFillPattern) { - fillPattern = dirtyFlag || !el.__canvasFillPattern ? createCanvasPattern(ctx, fill, el) : el.__canvasFillPattern; - el.__canvasFillPattern = fillPattern; - } - - if (hasStrokePattern) { - strokePattern = dirtyFlag || !el.__canvasStrokePattern ? createCanvasPattern(ctx, stroke, el) : el.__canvasStrokePattern; - el.__canvasStrokePattern = fillPattern; - } - - if (hasFillGradient) { - ctx.fillStyle = fillGradient; - } else if (hasFillPattern) { - if (fillPattern) { - ctx.fillStyle = fillPattern; - } else { - hasFill = false; - } - } - - if (hasStrokeGradient) { - ctx.strokeStyle = strokeGradient; - } else if (hasStrokePattern) { - if (strokePattern) { - ctx.strokeStyle = strokePattern; - } else { - hasStroke = false; - } - } - } - - var scale = el.getGlobalScale(); - path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold); - var lineDash; - var lineDashOffset; - - if (ctx.setLineDash && style.lineDash) { - _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1]; - } - - var needsRebuild = true; - - if (firstDraw || dirtyFlag & SHAPE_CHANGED_BIT) { - path.setDPR(ctx.dpr); - - if (strokePart) { - path.setContext(null); - } else { - path.setContext(ctx); - needsRebuild = false; - } - - path.reset(); - el.buildPath(path, el.shape, inBatch); - path.toStatic(); - el.pathUpdated(); - } - - if (needsRebuild) { - path.rebuildPath(ctx, strokePart ? strokePercent : 1); - } - - if (lineDash) { - ctx.setLineDash(lineDash); - ctx.lineDashOffset = lineDashOffset; - } - - if (!inBatch) { - if (style.strokeFirst) { - if (hasStroke) { - doStrokePath(ctx, style); - } - - if (hasFill) { - doFillPath(ctx, style); - } - } else { - if (hasFill) { - doFillPath(ctx, style); - } - - if (hasStroke) { - doStrokePath(ctx, style); - } - } - } - - if (lineDash) { - ctx.setLineDash([]); - } - } - - function brushImage(ctx, el, style) { - var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload); - - if (!image || !isImageReady(image)) { - return; - } - - var x = style.x || 0; - var y = style.y || 0; - var width = el.getWidth(); - var height = el.getHeight(); - var aspect = image.width / image.height; - - if (width == null && height != null) { - width = height * aspect; - } else if (height == null && width != null) { - height = width / aspect; - } else if (width == null && height == null) { - width = image.width; - height = image.height; - } - - if (style.sWidth && style.sHeight) { - var sx = style.sx || 0; - var sy = style.sy || 0; - ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height); - } else if (style.sx && style.sy) { - var sx = style.sx; - var sy = style.sy; - var sWidth = width - sx; - var sHeight = height - sy; - ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height); - } else { - ctx.drawImage(image, x, y, width, height); - } - } - - function brushText(ctx, el, style) { - var _a; - - var text = style.text; - text != null && (text += ''); - - if (text) { - ctx.font = style.font || DEFAULT_FONT; - ctx.textAlign = style.textAlign; - ctx.textBaseline = style.textBaseline; - var lineDash = void 0; - var lineDashOffset = void 0; - - if (ctx.setLineDash && style.lineDash) { - _a = getLineDash(el), lineDash = _a[0], lineDashOffset = _a[1]; - } - - if (lineDash) { - ctx.setLineDash(lineDash); - ctx.lineDashOffset = lineDashOffset; - } - - if (style.strokeFirst) { - if (styleHasStroke(style)) { - ctx.strokeText(text, style.x, style.y); - } - - if (styleHasFill(style)) { - ctx.fillText(text, style.x, style.y); - } - } else { - if (styleHasFill(style)) { - ctx.fillText(text, style.x, style.y); - } - - if (styleHasStroke(style)) { - ctx.strokeText(text, style.x, style.y); - } - } - - if (lineDash) { - ctx.setLineDash([]); - } - } - } - - var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; - var STROKE_PROPS = [['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]]; - - function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) { - var styleChanged = false; - - if (!forceSetAll) { - prevStyle = prevStyle || {}; - - if (style === prevStyle) { - return false; - } - } - - if (forceSetAll || style.opacity !== prevStyle.opacity) { - flushPathDrawn(ctx, scope); - styleChanged = true; - var opacity = Math.max(Math.min(style.opacity, 1), 0); - ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity; - } - - if (forceSetAll || style.blend !== prevStyle.blend) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend; - } - - for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) { - var propName = SHADOW_NUMBER_PROPS[i]; - - if (forceSetAll || style[propName] !== prevStyle[propName]) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx[propName] = ctx.dpr * (style[propName] || 0); - } - } - - if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor; - } - - return styleChanged; - } - - function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) { - var style = getStyle(el, scope.inHover); - var prevStyle = forceSetAll ? null : prevEl && getStyle(prevEl, scope.inHover) || {}; - - if (style === prevStyle) { - return false; - } - - var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope); - - if (forceSetAll || style.fill !== prevStyle.fill) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - isValidStrokeFillStyle(style.fill) && (ctx.fillStyle = style.fill); - } - - if (forceSetAll || style.stroke !== prevStyle.stroke) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - isValidStrokeFillStyle(style.stroke) && (ctx.strokeStyle = style.stroke); - } - - if (forceSetAll || style.opacity !== prevStyle.opacity) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx.globalAlpha = style.opacity == null ? 1 : style.opacity; - } - - if (el.hasStroke()) { - var lineWidth = style.lineWidth; - var newLineWidth = lineWidth / (style.strokeNoScale && el.getLineScale ? el.getLineScale() : 1); - - if (ctx.lineWidth !== newLineWidth) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx.lineWidth = newLineWidth; - } - } - - for (var i = 0; i < STROKE_PROPS.length; i++) { - var prop = STROKE_PROPS[i]; - var propName = prop[0]; - - if (forceSetAll || style[propName] !== prevStyle[propName]) { - if (!styleChanged) { - flushPathDrawn(ctx, scope); - styleChanged = true; - } - - ctx[propName] = style[propName] || prop[1]; - } - } - - return styleChanged; - } - - function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) { - return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope); - } - - function setContextTransform(ctx, el) { - var m = el.transform; - var dpr = ctx.dpr || 1; - - if (m) { - ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]); - } else { - ctx.setTransform(dpr, 0, 0, dpr, 0, 0); - } - } - - function updateClipStatus(clipPaths, ctx, scope) { - var allClipped = false; - - for (var i = 0; i < clipPaths.length; i++) { - var clipPath = clipPaths[i]; - allClipped = allClipped || clipPath.isZeroArea(); - setContextTransform(ctx, clipPath); - ctx.beginPath(); - clipPath.buildPath(ctx, clipPath.shape); - ctx.clip(); - } - - scope.allClipped = allClipped; - } - - function isTransformChanged(m0, m1) { - if (m0 && m1) { - return m0[0] !== m1[0] || m0[1] !== m1[1] || m0[2] !== m1[2] || m0[3] !== m1[3] || m0[4] !== m1[4] || m0[5] !== m1[5]; - } else if (!m0 && !m1) { - return false; - } - - return true; - } - - var DRAW_TYPE_PATH = 1; - var DRAW_TYPE_IMAGE = 2; - var DRAW_TYPE_TEXT = 3; - var DRAW_TYPE_INCREMENTAL = 4; - - function canPathBatch(style) { - var hasFill = styleHasFill(style); - var hasStroke = styleHasStroke(style); - return !(style.lineDash || !(+hasFill ^ +hasStroke) || hasFill && typeof style.fill !== 'string' || hasStroke && typeof style.stroke !== 'string' || style.strokePercent < 1 || style.strokeOpacity < 1 || style.fillOpacity < 1); - } - - function flushPathDrawn(ctx, scope) { - scope.batchFill && ctx.fill(); - scope.batchStroke && ctx.stroke(); - scope.batchFill = ''; - scope.batchStroke = ''; - } - - function getStyle(el, inHover) { - return inHover ? el.__hoverStyle || el.style : el.style; - } - - function brushSingle(ctx, el) { - brush$1(ctx, el, { - inHover: false, - viewWidth: 0, - viewHeight: 0 - }, true); - } - - function brush$1(ctx, el, scope, isLast) { - var m = el.transform; - - if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) { - el.__dirty &= ~REDRAW_BIT; - el.__isRendered = false; - return; - } - - var clipPaths = el.__clipPaths; - var prevElClipPaths = scope.prevElClipPaths; - var forceSetTransform = false; - var forceSetStyle = false; - - if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) { - if (prevElClipPaths && prevElClipPaths.length) { - flushPathDrawn(ctx, scope); - ctx.restore(); - forceSetStyle = forceSetTransform = true; - scope.prevElClipPaths = null; - scope.allClipped = false; - scope.prevEl = null; - } - - if (clipPaths && clipPaths.length) { - flushPathDrawn(ctx, scope); - ctx.save(); - updateClipStatus(clipPaths, ctx, scope); - forceSetTransform = true; - } - - scope.prevElClipPaths = clipPaths; - } - - if (scope.allClipped) { - el.__isRendered = false; - return; - } - - el.beforeBrush && el.beforeBrush(); - el.innerBeforeBrush(); - var prevEl = scope.prevEl; - - if (!prevEl) { - forceSetStyle = forceSetTransform = true; - } - - var canBatchPath = el instanceof Path && el.autoBatch && canPathBatch(el.style); - - if (forceSetTransform || isTransformChanged(m, prevEl.transform)) { - flushPathDrawn(ctx, scope); - setContextTransform(ctx, el); - } else if (!canBatchPath) { - flushPathDrawn(ctx, scope); - } - - var style = getStyle(el, scope.inHover); - - if (el instanceof Path) { - if (scope.lastDrawType !== DRAW_TYPE_PATH) { - forceSetStyle = true; - scope.lastDrawType = DRAW_TYPE_PATH; - } - - bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); - - if (!canBatchPath || !scope.batchFill && !scope.batchStroke) { - ctx.beginPath(); - } - - brushPath(ctx, el, style, canBatchPath); - - if (canBatchPath) { - scope.batchFill = style.fill || ''; - scope.batchStroke = style.stroke || ''; - } - } else { - if (el instanceof TSpan) { - if (scope.lastDrawType !== DRAW_TYPE_TEXT) { - forceSetStyle = true; - scope.lastDrawType = DRAW_TYPE_TEXT; - } - - bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); - brushText(ctx, el, style); - } else if (el instanceof ZRImage) { - if (scope.lastDrawType !== DRAW_TYPE_IMAGE) { - forceSetStyle = true; - scope.lastDrawType = DRAW_TYPE_IMAGE; - } - - bindImageStyle(ctx, el, prevEl, forceSetStyle, scope); - brushImage(ctx, el, style); - } else if (el.getTemporalDisplayables) { - if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) { - forceSetStyle = true; - scope.lastDrawType = DRAW_TYPE_INCREMENTAL; - } - - brushIncremental(ctx, el, scope); - } - } - - if (canBatchPath && isLast) { - flushPathDrawn(ctx, scope); - } - - el.innerAfterBrush(); - el.afterBrush && el.afterBrush(); - scope.prevEl = el; - el.__dirty = 0; - el.__isRendered = true; - } - - function brushIncremental(ctx, el, scope) { - var displayables = el.getDisplayables(); - var temporalDisplayables = el.getTemporalDisplayables(); - ctx.save(); - var innerScope = { - prevElClipPaths: null, - prevEl: null, - allClipped: false, - viewWidth: scope.viewWidth, - viewHeight: scope.viewHeight, - inHover: scope.inHover - }; - var i; - var len; - - for (i = el.getCursor(), len = displayables.length; i < len; i++) { - var displayable = displayables[i]; - displayable.beforeBrush && displayable.beforeBrush(); - displayable.innerBeforeBrush(); - brush$1(ctx, displayable, innerScope, i === len - 1); - displayable.innerAfterBrush(); - displayable.afterBrush && displayable.afterBrush(); - innerScope.prevEl = displayable; - } - - for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) { - var displayable = temporalDisplayables[i_1]; - displayable.beforeBrush && displayable.beforeBrush(); - displayable.innerBeforeBrush(); - brush$1(ctx, displayable, innerScope, i_1 === len_1 - 1); - displayable.innerAfterBrush(); - displayable.afterBrush && displayable.afterBrush(); - innerScope.prevEl = displayable; - } - - el.clearTemporalDisplayables(); - el.notClear = true; - ctx.restore(); - } - - var decalMap = new WeakMap(); - var decalCache = new LRU(100); - var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'maxTileWidth', 'maxTileHeight']; - /** - * Create or update pattern image from decal options - * - * @param {InnerDecalObject | 'none'} decalObject decal options, 'none' if no decal - * @return {Pattern} pattern with generated image, null if no decal - */ - - function createOrUpdatePatternFromDecal(decalObject, api) { - if (decalObject === 'none') { - return null; - } - - var dpr = api.getDevicePixelRatio(); - var zr = api.getZr(); - var isSVG = zr.painter.type === 'svg'; - - if (decalObject.dirty) { - decalMap["delete"](decalObject); - } - - var oldPattern = decalMap.get(decalObject); - - if (oldPattern) { - return oldPattern; - } - - var decalOpt = defaults(decalObject, { - symbol: 'rect', - symbolSize: 1, - symbolKeepAspect: true, - color: 'rgba(0, 0, 0, 0.2)', - backgroundColor: null, - dashArrayX: 5, - dashArrayY: 5, - rotation: 0, - maxTileWidth: 512, - maxTileHeight: 512 - }); - - if (decalOpt.backgroundColor === 'none') { - decalOpt.backgroundColor = null; - } - - var pattern = { - repeat: 'repeat' - }; - setPatternnSource(pattern); - pattern.rotation = decalOpt.rotation; - pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr; - decalMap.set(decalObject, pattern); - decalObject.dirty = false; - return pattern; - - function setPatternnSource(pattern) { - var keys = [dpr]; - var isValidKey = true; - - for (var i = 0; i < decalKeys.length; ++i) { - var value = decalOpt[decalKeys[i]]; - - if (value != null && !isArray(value) && !isString(value) && !isNumber(value) && typeof value !== 'boolean') { - isValidKey = false; - break; - } - - keys.push(value); - } - - var cacheKey; - - if (isValidKey) { - cacheKey = keys.join(',') + (isSVG ? '-svg' : ''); - var cache = decalCache.get(cacheKey); - - if (cache) { - isSVG ? pattern.svgElement = cache : pattern.image = cache; - } - } - - var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX); - var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY); - var symbolArray = normalizeSymbolArray(decalOpt.symbol); - var lineBlockLengthsX = getLineBlockLengthX(dashArrayX); - var lineBlockLengthY = getLineBlockLengthY(dashArrayY); - var canvas = !isSVG && platformApi.createCanvas(); - var svgRoot = isSVG && { - tag: 'g', - attrs: {}, - key: 'dcl', - children: [] - }; - var pSize = getPatternSize(); - var ctx; - - if (canvas) { - canvas.width = pSize.width * dpr; - canvas.height = pSize.height * dpr; - ctx = canvas.getContext('2d'); - } - - brushDecal(); - - if (isValidKey) { - decalCache.put(cacheKey, canvas || svgRoot); - } - - pattern.image = canvas; - pattern.svgElement = svgRoot; - pattern.svgWidth = pSize.width; - pattern.svgHeight = pSize.height; - /** - * Get minimum length that can make a repeatable pattern. - * - * @return {Object} pattern width and height - */ - - function getPatternSize() { - /** - * For example, if dash is [[3, 2], [2, 1]] for X, it looks like - * |--- --- --- --- --- ... - * |-- -- -- -- -- -- -- -- ... - * |--- --- --- --- --- ... - * |-- -- -- -- -- -- -- -- ... - * So the minimum length of X is 15, - * which is the least common multiple of `3 + 2` and `2 + 1` - * |--- --- --- |--- --- ... - * |-- -- -- -- -- |-- -- -- ... - */ - var width = 1; - - for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) { - width = getLeastCommonMultiple(width, lineBlockLengthsX[i]); - } - - var symbolRepeats = 1; - - for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) { - symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length); - } - - width *= symbolRepeats; - var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length; - { - var warn = function (attrName) { - /* eslint-disable-next-line */ - console.warn("Calculated decal size is greater than " + attrName + " due to decal option settings so " + attrName + " is used for the decal size. Please consider changing the decal option to make a smaller decal or set " + attrName + " to be larger to avoid incontinuity."); - }; - - if (width > decalOpt.maxTileWidth) { - warn('maxTileWidth'); - } - - if (height > decalOpt.maxTileHeight) { - warn('maxTileHeight'); - } - } - return { - width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)), - height: Math.max(1, Math.min(height, decalOpt.maxTileHeight)) - }; - } - - function brushDecal() { - if (ctx) { - ctx.clearRect(0, 0, canvas.width, canvas.height); - - if (decalOpt.backgroundColor) { - ctx.fillStyle = decalOpt.backgroundColor; - ctx.fillRect(0, 0, canvas.width, canvas.height); - } - } - - var ySum = 0; - - for (var i = 0; i < dashArrayY.length; ++i) { - ySum += dashArrayY[i]; - } - - if (ySum <= 0) { - // dashArrayY is 0, draw nothing - return; - } - - var y = -lineBlockLengthY; - var yId = 0; - var yIdTotal = 0; - var xId0 = 0; - - while (y < pSize.height) { - if (yId % 2 === 0) { - var symbolYId = yIdTotal / 2 % symbolArray.length; - var x = 0; - var xId1 = 0; - var xId1Total = 0; - - while (x < pSize.width * 2) { - var xSum = 0; - - for (var i = 0; i < dashArrayX[xId0].length; ++i) { - xSum += dashArrayX[xId0][i]; - } - - if (xSum <= 0) { - // Skip empty line - break; - } // E.g., [15, 5, 20, 5] draws only for 15 and 20 - - - if (xId1 % 2 === 0) { - var size = (1 - decalOpt.symbolSize) * 0.5; - var left = x + dashArrayX[xId0][xId1] * size; - var top_1 = y + dashArrayY[yId] * size; - var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize; - var height = dashArrayY[yId] * decalOpt.symbolSize; - var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length; - brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]); - } - - x += dashArrayX[xId0][xId1]; - ++xId1Total; - ++xId1; - - if (xId1 === dashArrayX[xId0].length) { - xId1 = 0; - } - } - - ++xId0; - - if (xId0 === dashArrayX.length) { - xId0 = 0; - } - } - - y += dashArrayY[yId]; - ++yIdTotal; - ++yId; - - if (yId === dashArrayY.length) { - yId = 0; - } - } - - function brushSymbol(x, y, width, height, symbolType) { - var scale = isSVG ? 1 : dpr; - var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect); - - if (isSVG) { - var symbolVNode = zr.painter.renderOneToVNode(symbol); - - if (symbolVNode) { - svgRoot.children.push(symbolVNode); - } - } else { - // Paint to canvas for all other renderers. - brushSingle(ctx, symbol); - } - } - } - } - } - /** - * Convert symbol array into normalized array - * - * @param {string | (string | string[])[]} symbol symbol input - * @return {string[][]} normolized symbol array - */ - - - function normalizeSymbolArray(symbol) { - if (!symbol || symbol.length === 0) { - return [['rect']]; - } - - if (isString(symbol)) { - return [[symbol]]; - } - - var isAllString = true; - - for (var i = 0; i < symbol.length; ++i) { - if (!isString(symbol[i])) { - isAllString = false; - break; - } - } - - if (isAllString) { - return normalizeSymbolArray([symbol]); - } - - var result = []; - - for (var i = 0; i < symbol.length; ++i) { - if (isString(symbol[i])) { - result.push([symbol[i]]); - } else { - result.push(symbol[i]); - } - } - - return result; - } - /** - * Convert dash input into dashArray - * - * @param {DecalDashArrayX} dash dash input - * @return {number[][]} normolized dash array - */ - - - function normalizeDashArrayX(dash) { - if (!dash || dash.length === 0) { - return [[0, 0]]; - } - - if (isNumber(dash)) { - var dashValue = Math.ceil(dash); - return [[dashValue, dashValue]]; - } - /** - * [20, 5] should be normalized into [[20, 5]], - * while [20, [5, 10]] should be normalized into [[20, 20], [5, 10]] - */ - - - var isAllNumber = true; - - for (var i = 0; i < dash.length; ++i) { - if (!isNumber(dash[i])) { - isAllNumber = false; - break; - } - } - - if (isAllNumber) { - return normalizeDashArrayX([dash]); - } - - var result = []; - - for (var i = 0; i < dash.length; ++i) { - if (isNumber(dash[i])) { - var dashValue = Math.ceil(dash[i]); - result.push([dashValue, dashValue]); - } else { - var dashValue = map$1(dash[i], function (n) { - return Math.ceil(n); - }); - - if (dashValue.length % 2 === 1) { - // [4, 2, 1] means |---- - -- |---- - -- | - // so normalize it to be [4, 2, 1, 4, 2, 1] - result.push(dashValue.concat(dashValue)); - } else { - result.push(dashValue); - } - } - } - - return result; - } - /** - * Convert dash input into dashArray - * - * @param {DecalDashArrayY} dash dash input - * @return {number[]} normolized dash array - */ - - - function normalizeDashArrayY(dash) { - if (!dash || typeof dash === 'object' && dash.length === 0) { - return [0, 0]; - } - - if (isNumber(dash)) { - var dashValue_1 = Math.ceil(dash); - return [dashValue_1, dashValue_1]; - } - - var dashValue = map$1(dash, function (n) { - return Math.ceil(n); - }); - return dash.length % 2 ? dashValue.concat(dashValue) : dashValue; - } - /** - * Get block length of each line. A block is the length of dash line and space. - * For example, a line with [4, 1] has a dash line of 4 and a space of 1 after - * that, so the block length of this line is 5. - * - * @param {number[][]} dash dash array of X or Y - * @return {number[]} block length of each line - */ - - - function getLineBlockLengthX(dash) { - return map$1(dash, function (line) { - return getLineBlockLengthY(line); - }); - } - - function getLineBlockLengthY(dash) { - var blockLength = 0; - - for (var i = 0; i < dash.length; ++i) { - blockLength += dash[i]; - } - - if (dash.length % 2 === 1) { - // [4, 2, 1] means |---- - -- |---- - -- | - // So total length is (4 + 2 + 1) * 2 - return blockLength * 2; - } - - return blockLength; - } - - function decalVisual(ecModel, api) { - ecModel.eachRawSeries(function (seriesModel) { - if (ecModel.isSeriesFiltered(seriesModel)) { - return; - } - - var data = seriesModel.getData(); - - if (data.hasItemVisual()) { - data.each(function (idx) { - var decal = data.getItemVisual(idx, 'decal'); - - if (decal) { - var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); - itemStyle.decal = createOrUpdatePatternFromDecal(decal, api); - } - }); - } - - var decal = data.getVisual('decal'); - - if (decal) { - var style = data.getVisual('style'); - style.decal = createOrUpdatePatternFromDecal(decal, api); - } - }); - } - - var lifecycle = new Eventful(); // Implementation of exported APIs. For example registerMap, getMap. - // The implementations will be registered when installing the component. - // Avoid these code being bundled to the core module. - - var implsStore = {}; // TODO Type - - function registerImpl(name, impl) { - { - if (implsStore[name]) { - error("Already has an implementation of " + name + "."); - } - } - implsStore[name] = impl; - } - - function getImpl(name) { - { - if (!implsStore[name]) { - error("Implementation of " + name + " doesn't exists."); - } - } - return implsStore[name]; - } - - var version = '5.5.0'; - var dependencies = { - zrender: '5.5.0' - }; - var TEST_FRAME_REMAIN_TIME = 1; - var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent). - // So data stack stage should be in front of data processing stage. - - var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be - // put at the beginning of data processing. - - var PRIORITY_PROCESSOR_FILTER = 1000; - var PRIORITY_PROCESSOR_DEFAULT = 2000; - var PRIORITY_PROCESSOR_STATISTIC = 5000; - var PRIORITY_VISUAL_LAYOUT = 1000; - var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100; - var PRIORITY_VISUAL_GLOBAL = 2000; - var PRIORITY_VISUAL_CHART = 3000; - var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to - // overwrite the viusal result of component (like `visualMap`) - // using data item specific setting (like itemStyle.xxx on data item) - - var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on - // visual result like `symbolSize`. - - var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600; - var PRIORITY_VISUAL_BRUSH = 5000; - var PRIORITY_VISUAL_ARIA = 6000; - var PRIORITY_VISUAL_DECAL = 7000; - var PRIORITY = { - PROCESSOR: { - FILTER: PRIORITY_PROCESSOR_FILTER, - SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER, - STATISTIC: PRIORITY_PROCESSOR_STATISTIC - }, - VISUAL: { - LAYOUT: PRIORITY_VISUAL_LAYOUT, - PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT, - GLOBAL: PRIORITY_VISUAL_GLOBAL, - CHART: PRIORITY_VISUAL_CHART, - POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT, - COMPONENT: PRIORITY_VISUAL_COMPONENT, - BRUSH: PRIORITY_VISUAL_BRUSH, - CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM, - ARIA: PRIORITY_VISUAL_ARIA, - DECAL: PRIORITY_VISUAL_DECAL - } - }; // Main process have three entries: `setOption`, `dispatchAction` and `resize`, - // where they must not be invoked nestedly, except the only case: invoke - // dispatchAction with updateMethod "none" in main process. - // This flag is used to carry out this rule. - // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]). - - var IN_MAIN_PROCESS_KEY = '__flagInMainProcess'; - var PENDING_UPDATE = '__pendingUpdate'; - var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus'; - var ACTION_REG = /^[a-zA-Z0-9_]+$/; - var CONNECT_STATUS_KEY = '__connectUpdateStatus'; - var CONNECT_STATUS_PENDING = 0; - var CONNECT_STATUS_UPDATING = 1; - var CONNECT_STATUS_UPDATED = 2; - - function createRegisterEventWithLowercaseECharts(method) { - return function () { - var args = []; - - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - - if (this.isDisposed()) { - disposedWarning(this.id); - return; - } - - return toLowercaseNameAndCallEventful(this, method, args); - }; - } - - function createRegisterEventWithLowercaseMessageCenter(method) { - return function () { - var args = []; - - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - - return toLowercaseNameAndCallEventful(this, method, args); - }; - } - - function toLowercaseNameAndCallEventful(host, method, args) { - // `args[0]` is event name. Event name is all lowercase. - args[0] = args[0] && args[0].toLowerCase(); - return Eventful.prototype[method].apply(host, args); - } - - var MessageCenter = - /** @class */ - function (_super) { - __extends(MessageCenter, _super); - - function MessageCenter() { - return _super !== null && _super.apply(this, arguments) || this; - } - - return MessageCenter; - }(Eventful); - - var messageCenterProto = MessageCenter.prototype; - messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on'); - messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // --------------------------------------- - // Internal method names for class ECharts - // --------------------------------------- - - var prepare; - var prepareView; - var updateDirectly; - var updateMethods; - var doConvertPixel; - var updateStreamModes; - var doDispatchAction; - var flushPendingActions; - var triggerUpdatedEvent; - var bindRenderedEvent; - var bindMouseEvent; - var render; - var renderComponents; - var renderSeries; - var createExtensionAPI; - var enableConnect; - var markStatusToUpdate; - var applyChangedStates; - - var ECharts = - /** @class */ - function (_super) { - __extends(ECharts, _super); - - function ECharts(dom, // Theme name or themeOption. - theme, opts) { - var _this = _super.call(this, new ECEventProcessor()) || this; - - _this._chartsViews = []; - _this._chartsMap = {}; - _this._componentsViews = []; - _this._componentsMap = {}; // Can't dispatch action during rendering procedure - - _this._pendingActions = []; - opts = opts || {}; // Get theme by name - - if (isString(theme)) { - theme = themeStorage[theme]; - } - - _this._dom = dom; - var defaultRenderer = 'canvas'; - var defaultCoarsePointer = 'auto'; - var defaultUseDirtyRect = false; - { - var root = - /* eslint-disable-next-line */ - env.hasGlobalWindow ? window : global; - - if (root) { - defaultRenderer = retrieve2(root.__ECHARTS__DEFAULT__RENDERER__, defaultRenderer); - defaultCoarsePointer = retrieve2(root.__ECHARTS__DEFAULT__COARSE_POINTER, defaultCoarsePointer); - defaultUseDirtyRect = retrieve2(root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__, defaultUseDirtyRect); - } - } - - if (opts.ssr) { - registerSSRDataGetter(function (el) { - var ecData = getECData(el); - var dataIndex = ecData.dataIndex; - - if (dataIndex == null) { - return; - } - - var hashMap = createHashMap(); - hashMap.set('series_index', ecData.seriesIndex); - hashMap.set('data_index', dataIndex); - ecData.ssrType && hashMap.set('ssr_type', ecData.ssrType); - return hashMap; - }); - } - - var zr = _this._zr = init$1(dom, { - renderer: opts.renderer || defaultRenderer, - devicePixelRatio: opts.devicePixelRatio, - width: opts.width, - height: opts.height, - ssr: opts.ssr, - useDirtyRect: retrieve2(opts.useDirtyRect, defaultUseDirtyRect), - useCoarsePointer: retrieve2(opts.useCoarsePointer, defaultCoarsePointer), - pointerSize: opts.pointerSize - }); - _this._ssr = opts.ssr; // Expect 60 fps. - - _this._throttledZrFlush = throttle(bind$1(zr.flush, zr), 17); - theme = clone$3(theme); - theme && globalBackwardCompat(theme, true); - _this._theme = theme; - _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG); - _this._coordSysMgr = new CoordinateSystemManager(); - var api = _this._api = createExtensionAPI(_this); // Sort on demand - - function prioritySortFunc(a, b) { - return a.__prio - b.__prio; - } - - sort(visualFuncs, prioritySortFunc); - sort(dataProcessorFuncs, prioritySortFunc); - _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs); - _this._messageCenter = new MessageCenter(); // Init mouse events - - _this._initEvents(); // In case some people write `window.onresize = chart.resize` - - - _this.resize = bind$1(_this.resize, _this); - zr.animation.on('frame', _this._onframe, _this); - bindRenderedEvent(zr, _this); - bindMouseEvent(zr, _this); // ECharts instance can be used as value. - - setAsPrimitive(_this); - return _this; - } - - ECharts.prototype._onframe = function () { - if (this._disposed) { - return; - } - - applyChangedStates(this); - var scheduler = this._scheduler; // Lazy update - - if (this[PENDING_UPDATE]) { - var silent = this[PENDING_UPDATE].silent; - this[IN_MAIN_PROCESS_KEY] = true; - - try { - prepare(this); - updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams); - } catch (e) { - this[IN_MAIN_PROCESS_KEY] = false; - this[PENDING_UPDATE] = null; - throw e; - } // At present, in each frame, zrender performs: - // (1) animation step forward. - // (2) trigger('frame') (where this `_onframe` is called) - // (3) zrender flush (render). - // If we do nothing here, since we use `setToFinal: true`, the step (3) above - // will render the final state of the elements before the real animation started. - - - this._zr.flush(); - - this[IN_MAIN_PROCESS_KEY] = false; - this[PENDING_UPDATE] = null; - flushPendingActions.call(this, silent); - triggerUpdatedEvent.call(this, silent); - } // Avoid do both lazy update and progress in one frame. - else if (scheduler.unfinished) { - // Stream progress. - var remainTime = TEST_FRAME_REMAIN_TIME; - var ecModel = this._model; - var api = this._api; - scheduler.unfinished = false; - - do { - var startTime = +new Date(); - scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold. - - scheduler.performDataProcessorTasks(ecModel); - updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in - // each frame is not a good user experience. So we follow the rule that - // the extent of the coordinate system is determined in the first frame (the - // frame is executed immediately after task reset. - // this._coordSysMgr.update(ecModel, api); - // console.log('--- ec frame visual ---', remainTime); - - scheduler.performVisualTasks(ecModel); - renderSeries(this, this._model, api, 'remain', {}); - remainTime -= +new Date() - startTime; - } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event. - - - if (!scheduler.unfinished) { - this._zr.flush(); - } // Else, zr flushing be ensue within the same frame, - // because zr flushing is after onframe event. - - } - }; - - ECharts.prototype.getDom = function () { - return this._dom; - }; - - ECharts.prototype.getId = function () { - return this.id; - }; - - ECharts.prototype.getZr = function () { - return this._zr; - }; - - ECharts.prototype.isSSR = function () { - return this._ssr; - }; - /* eslint-disable-next-line */ - - - ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) { - if (this[IN_MAIN_PROCESS_KEY]) { - { - error('`setOption` should not be called during main process.'); - } - return; - } - - if (this._disposed) { - disposedWarning(this.id); - return; - } - - var silent; - var replaceMerge; - var transitionOpt; - - if (isObject$2(notMerge)) { - lazyUpdate = notMerge.lazyUpdate; - silent = notMerge.silent; - replaceMerge = notMerge.replaceMerge; - transitionOpt = notMerge.transition; - notMerge = notMerge.notMerge; - } - - this[IN_MAIN_PROCESS_KEY] = true; - - if (!this._model || notMerge) { - var optionManager = new OptionManager(this._api); - var theme = this._theme; - var ecModel = this._model = new GlobalModel(); - ecModel.scheduler = this._scheduler; - ecModel.ssr = this._ssr; - ecModel.init(null, null, null, theme, this._locale, optionManager); - } - - this._model.setOption(option, { - replaceMerge: replaceMerge - }, optionPreprocessorFuncs); - - var updateParams = { - seriesTransition: transitionOpt, - optionChanged: true - }; - - if (lazyUpdate) { - this[PENDING_UPDATE] = { - silent: silent, - updateParams: updateParams - }; - this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept. - // It should wake it up to make sure zrender start to render at the next frame. - - this.getZr().wakeUp(); - } else { - try { - prepare(this); - updateMethods.update.call(this, null, updateParams); - } catch (e) { - this[PENDING_UPDATE] = null; - this[IN_MAIN_PROCESS_KEY] = false; - throw e; - } // Ensure zr refresh sychronously, and then pixel in canvas can be - // fetched after `setOption`. - - - if (!this._ssr) { - // not use flush when using ssr mode. - this._zr.flush(); - } - - this[PENDING_UPDATE] = null; - this[IN_MAIN_PROCESS_KEY] = false; - flushPendingActions.call(this, silent); - triggerUpdatedEvent.call(this, silent); - } - }; - /** - * @deprecated - */ - - - ECharts.prototype.setTheme = function () { - deprecateLog('ECharts#setTheme() is DEPRECATED in ECharts 3.0'); - }; // We don't want developers to use getModel directly. - - - ECharts.prototype.getModel = function () { - return this._model; - }; - - ECharts.prototype.getOption = function () { - return this._model && this._model.getOption(); - }; - - ECharts.prototype.getWidth = function () { - return this._zr.getWidth(); - }; - - ECharts.prototype.getHeight = function () { - return this._zr.getHeight(); - }; - - ECharts.prototype.getDevicePixelRatio = function () { - return this._zr.painter.dpr - /* eslint-disable-next-line */ - || env.hasGlobalWindow && window.devicePixelRatio || 1; - }; - /** - * Get canvas which has all thing rendered - * @deprecated Use renderToCanvas instead. - */ - - - ECharts.prototype.getRenderedCanvas = function (opts) { - { - deprecateReplaceLog('getRenderedCanvas', 'renderToCanvas'); - } - return this.renderToCanvas(opts); - }; - - ECharts.prototype.renderToCanvas = function (opts) { - opts = opts || {}; - var painter = this._zr.painter; - { - if (painter.type !== 'canvas') { - throw new Error('renderToCanvas can only be used in the canvas renderer.'); - } - } - return painter.getRenderedCanvas({ - backgroundColor: opts.backgroundColor || this._model.get('backgroundColor'), - pixelRatio: opts.pixelRatio || this.getDevicePixelRatio() - }); - }; - - ECharts.prototype.renderToSVGString = function (opts) { - opts = opts || {}; - var painter = this._zr.painter; - { - if (painter.type !== 'svg') { - throw new Error('renderToSVGString can only be used in the svg renderer.'); - } - } - return painter.renderToString({ - useViewBox: opts.useViewBox - }); - }; - /** - * Get svg data url - */ - - - ECharts.prototype.getSvgDataURL = function () { - if (!env.svgSupported) { - return; - } - - var zr = this._zr; - var list = zr.storage.getDisplayList(); // Stop animations - - each$4(list, function (el) { - el.stopAnimation(null, true); - }); - return zr.painter.toDataURL(); - }; - - ECharts.prototype.getDataURL = function (opts) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - opts = opts || {}; - var excludeComponents = opts.excludeComponents; - var ecModel = this._model; - var excludesComponentViews = []; - var self = this; - each$4(excludeComponents, function (componentType) { - ecModel.eachComponent({ - mainType: componentType - }, function (component) { - var view = self._componentsMap[component.__viewId]; - - if (!view.group.ignore) { - excludesComponentViews.push(view); - view.group.ignore = true; - } - }); - }); - var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.renderToCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png')); - each$4(excludesComponentViews, function (view) { - view.group.ignore = false; - }); - return url; - }; - - ECharts.prototype.getConnectedDataURL = function (opts) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - var isSvg = opts.type === 'svg'; - var groupId = this.group; - var mathMin = Math.min; - var mathMax = Math.max; - var MAX_NUMBER = Infinity; - - if (connectedGroups[groupId]) { - var left_1 = MAX_NUMBER; - var top_1 = MAX_NUMBER; - var right_1 = -MAX_NUMBER; - var bottom_1 = -MAX_NUMBER; - var canvasList_1 = []; - var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio(); - each$4(instances, function (chart, id) { - if (chart.group === groupId) { - var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.renderToCanvas(clone$3(opts)); - var boundingRect = chart.getDom().getBoundingClientRect(); - left_1 = mathMin(boundingRect.left, left_1); - top_1 = mathMin(boundingRect.top, top_1); - right_1 = mathMax(boundingRect.right, right_1); - bottom_1 = mathMax(boundingRect.bottom, bottom_1); - canvasList_1.push({ - dom: canvas, - left: boundingRect.left, - top: boundingRect.top - }); - } - }); - left_1 *= dpr_1; - top_1 *= dpr_1; - right_1 *= dpr_1; - bottom_1 *= dpr_1; - var width = right_1 - left_1; - var height = bottom_1 - top_1; - var targetCanvas = platformApi.createCanvas(); - var zr_1 = init$1(targetCanvas, { - renderer: isSvg ? 'svg' : 'canvas' - }); - zr_1.resize({ - width: width, - height: height - }); - - if (isSvg) { - var content_1 = ''; - each$4(canvasList_1, function (item) { - var x = item.left - left_1; - var y = item.top - top_1; - content_1 += '' + item.dom + ''; - }); - zr_1.painter.getSvgRoot().innerHTML = content_1; - - if (opts.connectedBackgroundColor) { - zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor); - } - - zr_1.refreshImmediately(); - return zr_1.painter.toDataURL(); - } else { - // Background between the charts - if (opts.connectedBackgroundColor) { - zr_1.add(new Rect({ - shape: { - x: 0, - y: 0, - width: width, - height: height - }, - style: { - fill: opts.connectedBackgroundColor - } - })); - } - - each$4(canvasList_1, function (item) { - var img = new ZRImage({ - style: { - x: item.left * dpr_1 - left_1, - y: item.top * dpr_1 - top_1, - image: item.dom - } - }); - zr_1.add(img); - }); - zr_1.refreshImmediately(); - return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png')); - } - } else { - return this.getDataURL(opts); - } - }; - - ECharts.prototype.convertToPixel = function (finder, value) { - return doConvertPixel(this, 'convertToPixel', finder, value); - }; - - ECharts.prototype.convertFromPixel = function (finder, value) { - return doConvertPixel(this, 'convertFromPixel', finder, value); - }; - /** - * Is the specified coordinate systems or components contain the given pixel point. - * @param {Array|number} value - * @return {boolean} result - */ - - - ECharts.prototype.containPixel = function (finder, value) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - var ecModel = this._model; - var result; - var findResult = parseFinder(ecModel, finder); - each$4(findResult, function (models, key) { - key.indexOf('Models') >= 0 && each$4(models, function (model) { - var coordSys = model.coordinateSystem; - - if (coordSys && coordSys.containPoint) { - result = result || !!coordSys.containPoint(value); - } else if (key === 'seriesModels') { - var view = this._chartsMap[model.__viewId]; - - if (view && view.containPoint) { - result = result || view.containPoint(value, model); - } else { - { - warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.')); - } - } - } else { - { - warn(key + ': containPoint is not supported'); - } - } - }, this); - }, this); - return !!result; - }; - /** - * Get visual from series or data. - * @param finder - * If string, e.g., 'series', means {seriesIndex: 0}. - * If Object, could contain some of these properties below: - * { - * seriesIndex / seriesId / seriesName, - * dataIndex / dataIndexInside - * } - * If dataIndex is not specified, series visual will be fetched, - * but not data item visual. - * If all of seriesIndex, seriesId, seriesName are not specified, - * visual will be fetched from first series. - * @param visualType 'color', 'symbol', 'symbolSize' - */ - - - ECharts.prototype.getVisual = function (finder, visualType) { - var ecModel = this._model; - var parsedFinder = parseFinder(ecModel, finder, { - defaultMainType: 'series' - }); - var seriesModel = parsedFinder.seriesModel; - { - if (!seriesModel) { - warn('There is no specified series model'); - } - } - var data = seriesModel.getData(); - var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null; - return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType); - }; - /** - * Get view of corresponding component model - */ - - - ECharts.prototype.getViewOfComponentModel = function (componentModel) { - return this._componentsMap[componentModel.__viewId]; - }; - /** - * Get view of corresponding series model - */ - - - ECharts.prototype.getViewOfSeriesModel = function (seriesModel) { - return this._chartsMap[seriesModel.__viewId]; - }; - - ECharts.prototype._initEvents = function () { - var _this = this; - - each$4(MOUSE_EVENT_NAMES, function (eveName) { - var handler = function (e) { - var ecModel = _this.getModel(); - - var el = e.target; - var params; - var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'. - - if (isGlobalOut) { - params = {}; - } else { - el && findEventDispatcher(el, function (parent) { - var ecData = getECData(parent); - - if (ecData && ecData.dataIndex != null) { - var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex); - params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType, el) || {}; - return true; - } // If element has custom eventData of components - else if (ecData.eventData) { - params = extend({}, ecData.eventData); - return true; - } - }, true); - } // Contract: if params prepared in mouse event, - // these properties must be specified: - // { - // componentType: string (component main type) - // componentIndex: number - // } - // Otherwise event query can not work. - - - if (params) { - var componentType = params.componentType; - var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by - // markLine/markPoint/markArea, the componentType is - // 'markLine'/'markPoint'/'markArea', but we should better - // enable them to be queried by seriesIndex, since their - // option is set in each series. - - if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') { - componentType = 'series'; - componentIndex = params.seriesIndex; - } - - var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex); - var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]; - { - // `event.componentType` and `event[componentTpype + 'Index']` must not - // be missed, otherwise there is no way to distinguish source component. - // See `dataFormat.getDataParams`. - if (!isGlobalOut && !(model && view)) { - warn('model or view can not be found by params'); - } - } - params.event = e; - params.type = eveName; - _this._$eventProcessor.eventInfo = { - targetEl: el, - packedEvent: params, - model: model, - view: view - }; - - _this.trigger(eveName, params); - } - }; // Consider that some component (like tooltip, brush, ...) - // register zr event handler, but user event handler might - // do anything, such as call `setOption` or `dispatchAction`, - // which probably update any of the content and probably - // cause problem if it is called previous other inner handlers. - - - handler.zrEventfulCallAtLast = true; - - _this._zr.on(eveName, handler, _this); - }); - each$4(eventActionMap, function (actionType, eventType) { - _this._messageCenter.on(eventType, function (event) { - this.trigger(eventType, event); - }, _this); - }); // Extra events - // TODO register? - - each$4(['selectchanged'], function (eventType) { - _this._messageCenter.on(eventType, function (event) { - this.trigger(eventType, event); - }, _this); - }); - handleLegacySelectEvents(this._messageCenter, this, this._api); - }; - - ECharts.prototype.isDisposed = function () { - return this._disposed; - }; - - ECharts.prototype.clear = function () { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - this.setOption({ - series: [] - }, true); - }; - - ECharts.prototype.dispose = function () { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - this._disposed = true; - var dom = this.getDom(); - - if (dom) { - setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, ''); - } - - var chart = this; - var api = chart._api; - var ecModel = chart._model; - each$4(chart._componentsViews, function (component) { - component.dispose(ecModel, api); - }); - each$4(chart._chartsViews, function (chart) { - chart.dispose(ecModel, api); - }); // Dispose after all views disposed - - chart._zr.dispose(); // Set properties to null. - // To reduce the memory cost in case the top code still holds this instance unexpectedly. - - - chart._dom = chart._model = chart._chartsMap = chart._componentsMap = chart._chartsViews = chart._componentsViews = chart._scheduler = chart._api = chart._zr = chart._throttledZrFlush = chart._theme = chart._coordSysMgr = chart._messageCenter = null; - delete instances[chart.id]; - }; - /** - * Resize the chart - */ - - - ECharts.prototype.resize = function (opts) { - if (this[IN_MAIN_PROCESS_KEY]) { - { - error('`resize` should not be called during main process.'); - } - return; - } - - if (this._disposed) { - disposedWarning(this.id); - return; - } - - this._zr.resize(opts); - - var ecModel = this._model; // Resize loading effect - - this._loadingFX && this._loadingFX.resize(); - - if (!ecModel) { - return; - } - - var needPrepare = ecModel.resetOption('media'); - var silent = opts && opts.silent; // There is some real cases that: - // chart.setOption(option, { lazyUpdate: true }); - // chart.resize(); - - if (this[PENDING_UPDATE]) { - if (silent == null) { - silent = this[PENDING_UPDATE].silent; - } - - needPrepare = true; - this[PENDING_UPDATE] = null; - } - - this[IN_MAIN_PROCESS_KEY] = true; - - try { - needPrepare && prepare(this); - updateMethods.update.call(this, { - type: 'resize', - animation: extend({ - // Disable animation - duration: 0 - }, opts && opts.animation) - }); - } catch (e) { - this[IN_MAIN_PROCESS_KEY] = false; - throw e; - } - - this[IN_MAIN_PROCESS_KEY] = false; - flushPendingActions.call(this, silent); - triggerUpdatedEvent.call(this, silent); - }; - - ECharts.prototype.showLoading = function (name, cfg) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - if (isObject$2(name)) { - cfg = name; - name = ''; - } - - name = name || 'default'; - this.hideLoading(); - - if (!loadingEffects[name]) { - { - warn('Loading effects ' + name + ' not exists.'); - } - return; - } - - var el = loadingEffects[name](this._api, cfg); - var zr = this._zr; - this._loadingFX = el; - zr.add(el); - }; - /** - * Hide loading effect - */ - - - ECharts.prototype.hideLoading = function () { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - this._loadingFX && this._zr.remove(this._loadingFX); - this._loadingFX = null; - }; - - ECharts.prototype.makeActionFromEvent = function (eventObj) { - var payload = extend({}, eventObj); - payload.type = eventActionMap[eventObj.type]; - return payload; - }; - /** - * @param opt If pass boolean, means opt.silent - * @param opt.silent Default `false`. Whether trigger events. - * @param opt.flush Default `undefined`. - * true: Flush immediately, and then pixel in canvas can be fetched - * immediately. Caution: it might affect performance. - * false: Not flush. - * undefined: Auto decide whether perform flush. - */ - - - ECharts.prototype.dispatchAction = function (payload, opt) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - if (!isObject$2(opt)) { - opt = { - silent: !!opt - }; - } - - if (!actions[payload.type]) { - return; - } // Avoid dispatch action before setOption. Especially in `connect`. - - - if (!this._model) { - return; - } // May dispatchAction in rendering procedure - - - if (this[IN_MAIN_PROCESS_KEY]) { - this._pendingActions.push(payload); - - return; - } - - var silent = opt.silent; - doDispatchAction.call(this, payload, silent); - var flush = opt.flush; - - if (flush) { - this._zr.flush(); - } else if (flush !== false && env.browser.weChat) { - // In WeChat embedded browser, `requestAnimationFrame` and `setInterval` - // hang when sliding page (on touch event), which cause that zr does not - // refresh until user interaction finished, which is not expected. - // But `dispatchAction` may be called too frequently when pan on touch - // screen, which impacts performance if do not throttle them. - this._throttledZrFlush(); - } - - flushPendingActions.call(this, silent); - triggerUpdatedEvent.call(this, silent); - }; - - ECharts.prototype.updateLabelLayout = function () { - lifecycle.trigger('series:layoutlabels', this._model, this._api, { - // Not adding series labels. - // TODO - updatedSeries: [] - }); - }; - - ECharts.prototype.appendData = function (params) { - if (this._disposed) { - disposedWarning(this.id); - return; - } - - var seriesIndex = params.seriesIndex; - var ecModel = this.getModel(); - var seriesModel = ecModel.getSeriesByIndex(seriesIndex); - { - assert(params.data && seriesModel); - } - seriesModel.appendData(params); // Note: `appendData` does not support that update extent of coordinate - // system, util some scenario require that. In the expected usage of - // `appendData`, the initial extent of coordinate system should better - // be fixed by axis `min`/`max` setting or initial data, otherwise if - // the extent changed while `appendData`, the location of the painted - // graphic elements have to be changed, which make the usage of - // `appendData` meaningless. - - this._scheduler.unfinished = true; - this.getZr().wakeUp(); - }; // A work around for no `internal` modifier in ts yet but - // need to strictly hide private methods to JS users. - - - ECharts.internalField = function () { - prepare = function (ecIns) { - var scheduler = ecIns._scheduler; - scheduler.restorePipelines(ecIns._model); - scheduler.prepareStageTasks(); - prepareView(ecIns, true); - prepareView(ecIns, false); - scheduler.plan(); - }; - /** - * Prepare view instances of charts and components - */ - - - prepareView = function (ecIns, isComponent) { - var ecModel = ecIns._model; - var scheduler = ecIns._scheduler; - var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews; - var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap; - var zr = ecIns._zr; - var api = ecIns._api; - - for (var i = 0; i < viewList.length; i++) { - viewList[i].__alive = false; - } - - isComponent ? ecModel.eachComponent(function (componentType, model) { - componentType !== 'series' && doPrepare(model); - }) : ecModel.eachSeries(doPrepare); - - function doPrepare(model) { - // By default view will be reused if possible for the case that `setOption` with "notMerge" - // mode and need to enable transition animation. (Usually, when they have the same id, or - // especially no id but have the same type & name & index. See the `model.id` generation - // rule in `makeIdAndName` and `viewId` generation rule here). - // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that - // the new model has nothing to do with the old model. - var requireNewView = model.__requireNewView; // This command should not work twice. - - model.__requireNewView = false; // Consider: id same and type changed. - - var viewId = '_ec_' + model.id + '_' + model.type; - var view = !requireNewView && viewMap[viewId]; - - if (!view) { - var classType = parseClassType(model.type); - var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : // FIXME:TS - // (ChartView as ChartViewConstructor).getClass('series', classType.sub) - // For backward compat, still support a chart type declared as only subType - // like "liquidfill", but recommend "series.liquidfill" - // But need a base class to make a type series. - ChartView.getClass(classType.sub); - { - assert(Clazz, classType.sub + ' does not exist.'); - } - view = new Clazz(); - view.init(ecModel, api); - viewMap[viewId] = view; - viewList.push(view); - zr.add(view.group); - } - - model.__viewId = view.__id = viewId; - view.__alive = true; - view.__model = model; - view.group.__ecComponentInfo = { - mainType: model.mainType, - index: model.componentIndex - }; - !isComponent && scheduler.prepareView(view, model, ecModel, api); - } - - for (var i = 0; i < viewList.length;) { - var view = viewList[i]; - - if (!view.__alive) { - !isComponent && view.renderTask.dispose(); - zr.remove(view.group); - view.dispose(ecModel, api); - viewList.splice(i, 1); - - if (viewMap[view.__id] === view) { - delete viewMap[view.__id]; - } - - view.__id = view.group.__ecComponentInfo = null; - } else { - i++; - } - } - }; - - updateDirectly = function (ecIns, method, payload, mainType, subType) { - var ecModel = ecIns._model; - ecModel.setUpdatePayload(payload); // broadcast - - if (!mainType) { - // FIXME - // Chart will not be update directly here, except set dirty. - // But there is no such scenario now. - each$4([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView); - return; - } - - var query = {}; - query[mainType + 'Id'] = payload[mainType + 'Id']; - query[mainType + 'Index'] = payload[mainType + 'Index']; - query[mainType + 'Name'] = payload[mainType + 'Name']; - var condition = { - mainType: mainType, - query: query - }; - subType && (condition.subType = subType); // subType may be '' by parseClassType; - - var excludeSeriesId = payload.excludeSeriesId; - var excludeSeriesIdMap; - - if (excludeSeriesId != null) { - excludeSeriesIdMap = createHashMap(); - each$4(normalizeToArray(excludeSeriesId), function (id) { - var modelId = convertOptionIdName(id, null); - - if (modelId != null) { - excludeSeriesIdMap.set(modelId, true); - } - }); - } // If dispatchAction before setOption, do nothing. - - - ecModel && ecModel.eachComponent(condition, function (model) { - var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null; - - if (isExcluded) { - return; - } - - if (isHighDownPayload(payload)) { - if (model instanceof SeriesModel) { - if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur && !model.get(['emphasis', 'disabled'])) { - blurSeriesFromHighlightPayload(model, payload, ecIns._api); - } - } else { - var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api), - focusSelf = _a.focusSelf, - dispatchers = _a.dispatchers; - - if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) { - blurComponent(model.mainType, model.componentIndex, ecIns._api); - } // PENDING: - // Whether to put this "enter emphasis" code in `ComponentView`, - // which will be the same as `ChartView` but might be not necessary - // and will be far from this logic. - - - if (dispatchers) { - each$4(dispatchers, function (dispatcher) { - payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher); - }); - } - } - } else if (isSelectChangePayload(payload)) { - // TODO geo - if (model instanceof SeriesModel) { - toggleSelectionFromPayload(model, payload, ecIns._api); - updateSeriesElementSelection(model); - markStatusToUpdate(ecIns); - } - } - }, ecIns); - ecModel && ecModel.eachComponent(condition, function (model) { - var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null; - - if (isExcluded) { - return; - } - - callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]); - }, ecIns); - - function callView(view) { - view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload); - } - }; - - updateMethods = { - prepareAndUpdate: function (payload) { - prepare(this); - updateMethods.update.call(this, payload, { - // Needs to mark option changed if newOption is given. - // It's from MagicType. - // TODO If use a separate flag optionChanged in payload? - optionChanged: payload.newOption != null - }); - }, - update: function (payload, updateParams) { - var ecModel = this._model; - var api = this._api; - var zr = this._zr; - var coordSysMgr = this._coordSysMgr; - var scheduler = this._scheduler; // update before setOption - - if (!ecModel) { - return; - } - - ecModel.setUpdatePayload(payload); - scheduler.restoreData(ecModel, payload); - scheduler.performSeriesTasks(ecModel); // TODO - // Save total ecModel here for undo/redo (after restoring data and before processing data). - // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call. - // Create new coordinate system each update - // In LineView may save the old coordinate system and use it to get the original point. - - coordSysMgr.create(ecModel, api); - scheduler.performDataProcessorTasks(ecModel, payload); // Current stream render is not supported in data process. So we can update - // stream modes after data processing, where the filtered data is used to - // determine whether to use progressive rendering. - - updateStreamModes(this, ecModel); // We update stream modes before coordinate system updated, then the modes info - // can be fetched when coord sys updating (consider the barGrid extent fix). But - // the drawback is the full coord info can not be fetched. Fortunately this full - // coord is not required in stream mode updater currently. - - coordSysMgr.update(ecModel, api); - clearColorPalette(ecModel); - scheduler.performVisualTasks(ecModel, payload); - render(this, ecModel, api, payload, updateParams); // Set background - - var backgroundColor = ecModel.get('backgroundColor') || 'transparent'; - var darkMode = ecModel.get('darkMode'); - zr.setBackgroundColor(backgroundColor); // Force set dark mode. - - if (darkMode != null && darkMode !== 'auto') { - zr.setDarkMode(darkMode); - } - - lifecycle.trigger('afterupdate', ecModel, api); - }, - updateTransform: function (payload) { - var _this = this; - - var ecModel = this._model; - var api = this._api; // update before setOption - - if (!ecModel) { - return; - } - - ecModel.setUpdatePayload(payload); // ChartView.markUpdateMethod(payload, 'updateTransform'); - - var componentDirtyList = []; - ecModel.eachComponent(function (componentType, componentModel) { - if (componentType === 'series') { - return; - } - - var componentView = _this.getViewOfComponentModel(componentModel); - - if (componentView && componentView.__alive) { - if (componentView.updateTransform) { - var result = componentView.updateTransform(componentModel, ecModel, api, payload); - result && result.update && componentDirtyList.push(componentView); - } else { - componentDirtyList.push(componentView); - } - } - }); - var seriesDirtyMap = createHashMap(); - ecModel.eachSeries(function (seriesModel) { - var chartView = _this._chartsMap[seriesModel.__viewId]; - - if (chartView.updateTransform) { - var result = chartView.updateTransform(seriesModel, ecModel, api, payload); - result && result.update && seriesDirtyMap.set(seriesModel.uid, 1); - } else { - seriesDirtyMap.set(seriesModel.uid, 1); - } - }); - clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. - // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true); - - this._scheduler.performVisualTasks(ecModel, payload, { - setDirty: true, - dirtyMap: seriesDirtyMap - }); // Currently, not call render of components. Geo render cost a lot. - // renderComponents(ecIns, ecModel, api, payload, componentDirtyList); - - - renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap); - lifecycle.trigger('afterupdate', ecModel, api); - }, - updateView: function (payload) { - var ecModel = this._model; // update before setOption - - if (!ecModel) { - return; - } - - ecModel.setUpdatePayload(payload); - ChartView.markUpdateMethod(payload, 'updateView'); - clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. - - this._scheduler.performVisualTasks(ecModel, payload, { - setDirty: true - }); - - render(this, ecModel, this._api, payload, {}); - lifecycle.trigger('afterupdate', ecModel, this._api); - }, - updateVisual: function (payload) { - // updateMethods.update.call(this, payload); - var _this = this; - - var ecModel = this._model; // update before setOption - - if (!ecModel) { - return; - } - - ecModel.setUpdatePayload(payload); // clear all visual - - ecModel.eachSeries(function (seriesModel) { - seriesModel.getData().clearAllVisual(); - }); // Perform visual - - ChartView.markUpdateMethod(payload, 'updateVisual'); - clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline. - - this._scheduler.performVisualTasks(ecModel, payload, { - visualType: 'visual', - setDirty: true - }); - - ecModel.eachComponent(function (componentType, componentModel) { - if (componentType !== 'series') { - var componentView = _this.getViewOfComponentModel(componentModel); - - componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload); - } - }); - ecModel.eachSeries(function (seriesModel) { - var chartView = _this._chartsMap[seriesModel.__viewId]; - chartView.updateVisual(seriesModel, ecModel, _this._api, payload); - }); - lifecycle.trigger('afterupdate', ecModel, this._api); - }, - updateLayout: function (payload) { - updateMethods.update.call(this, payload); - } - }; - - doConvertPixel = function (ecIns, methodName, finder, value) { - if (ecIns._disposed) { - disposedWarning(ecIns.id); - return; - } - - var ecModel = ecIns._model; - - var coordSysList = ecIns._coordSysMgr.getCoordinateSystems(); - - var result; - var parsedFinder = parseFinder(ecModel, finder); - - for (var i = 0; i < coordSysList.length; i++) { - var coordSys = coordSysList[i]; - - if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) { - return result; - } - } - - { - warn('No coordinate system that supports ' + methodName + ' found by the given finder.'); - } - }; - - updateStreamModes = function (ecIns, ecModel) { - var chartsMap = ecIns._chartsMap; - var scheduler = ecIns._scheduler; - ecModel.eachSeries(function (seriesModel) { - scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]); - }); - }; - - doDispatchAction = function (payload, silent) { - var _this = this; - - var ecModel = this.getModel(); - var payloadType = payload.type; - var escapeConnect = payload.escapeConnect; - var actionWrap = actions[payloadType]; - var actionInfo = actionWrap.actionInfo; - var cptTypeTmp = (actionInfo.update || 'update').split(':'); - var updateMethod = cptTypeTmp.pop(); - var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]); - this[IN_MAIN_PROCESS_KEY] = true; - var payloads = [payload]; - var batched = false; // Batch action - - if (payload.batch) { - batched = true; - payloads = map$1(payload.batch, function (item) { - item = defaults(extend({}, item), payload); - item.batch = null; - return item; - }); - } - - var eventObjBatch = []; - var eventObj; - var isSelectChange = isSelectChangePayload(payload); - var isHighDown = isHighDownPayload(payload); // Only leave blur once if there are multiple batches. - - if (isHighDown) { - allLeaveBlur(this._api); - } - - each$4(payloads, function (batchItem) { - // Action can specify the event by return it. - eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside - - eventObj = eventObj || extend({}, batchItem); // Convert type to eventType - - eventObj.type = actionInfo.event || eventObj.type; - eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual. - - if (isHighDown) { - var _a = preParseFinder(payload), - queryOptionMap = _a.queryOptionMap, - mainTypeSpecified = _a.mainTypeSpecified; - - var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series'; - updateDirectly(_this, updateMethod, batchItem, componentMainType); - markStatusToUpdate(_this); - } else if (isSelectChange) { - // At present `dispatchAction({ type: 'select', ... })` is not supported on components. - // geo still use 'geoselect'. - updateDirectly(_this, updateMethod, batchItem, 'series'); - markStatusToUpdate(_this); - } else if (cptType) { - updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub); - } - }); - - if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) { - try { - // Still dirty - if (this[PENDING_UPDATE]) { - prepare(this); - updateMethods.update.call(this, payload); - this[PENDING_UPDATE] = null; - } else { - updateMethods[updateMethod].call(this, payload); - } - } catch (e) { - this[IN_MAIN_PROCESS_KEY] = false; - throw e; - } - } // Follow the rule of action batch - - - if (batched) { - eventObj = { - type: actionInfo.event || payloadType, - escapeConnect: escapeConnect, - batch: eventObjBatch - }; - } else { - eventObj = eventObjBatch[0]; - } - - this[IN_MAIN_PROCESS_KEY] = false; - - if (!silent) { - var messageCenter = this._messageCenter; - messageCenter.trigger(eventObj.type, eventObj); // Extra triggered 'selectchanged' event - - if (isSelectChange) { - var newObj = { - type: 'selectchanged', - escapeConnect: escapeConnect, - selected: getAllSelectedIndices(ecModel), - isFromClick: payload.isFromClick || false, - fromAction: payload.type, - fromActionPayload: payload - }; - messageCenter.trigger(newObj.type, newObj); - } - } - }; - - flushPendingActions = function (silent) { - var pendingActions = this._pendingActions; - - while (pendingActions.length) { - var payload = pendingActions.shift(); - doDispatchAction.call(this, payload, silent); - } - }; - - triggerUpdatedEvent = function (silent) { - !silent && this.trigger('updated'); - }; - /** - * Event `rendered` is triggered when zr - * rendered. It is useful for realtime - * snapshot (reflect animation). - * - * Event `finished` is triggered when: - * (1) zrender rendering finished. - * (2) initial animation finished. - * (3) progressive rendering finished. - * (4) no pending action. - * (5) no delayed setOption needs to be processed. - */ - - - bindRenderedEvent = function (zr, ecIns) { - zr.on('rendered', function (params) { - ecIns.trigger('rendered', params); // The `finished` event should not be triggered repeatedly, - // so it should only be triggered when rendering indeed happens - // in zrender. (Consider the case that dipatchAction is keep - // triggering when mouse move). - - if ( // Although zr is dirty if initial animation is not finished - // and this checking is called on frame, we also check - // animation finished for robustness. - zr.animation.isFinished() && !ecIns[PENDING_UPDATE] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) { - ecIns.trigger('finished'); - } - }); - }; - - bindMouseEvent = function (zr, ecIns) { - zr.on('mouseover', function (e) { - var el = e.target; - var dispatcher = findEventDispatcher(el, isHighDownDispatcher); - - if (dispatcher) { - handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api); - markStatusToUpdate(ecIns); - } - }).on('mouseout', function (e) { - var el = e.target; - var dispatcher = findEventDispatcher(el, isHighDownDispatcher); - - if (dispatcher) { - handleGlobalMouseOutForHighDown(dispatcher, e, ecIns._api); - markStatusToUpdate(ecIns); - } - }).on('click', function (e) { - var el = e.target; - var dispatcher = findEventDispatcher(el, function (target) { - return getECData(target).dataIndex != null; - }, true); - - if (dispatcher) { - var actionType = dispatcher.selected ? 'unselect' : 'select'; - var ecData = getECData(dispatcher); - - ecIns._api.dispatchAction({ - type: actionType, - dataType: ecData.dataType, - dataIndexInside: ecData.dataIndex, - seriesIndex: ecData.seriesIndex, - isFromClick: true - }); - } - }); - }; - - function clearColorPalette(ecModel) { - ecModel.clearColorPalette(); - ecModel.eachSeries(function (seriesModel) { - seriesModel.clearColorPalette(); - }); - } // Allocate zlevels for series and components - - - function allocateZlevels(ecModel) { - var componentZLevels = []; - var seriesZLevels = []; - var hasSeparateZLevel = false; - ecModel.eachComponent(function (componentType, componentModel) { - var zlevel = componentModel.get('zlevel') || 0; - var z = componentModel.get('z') || 0; - var zlevelKey = componentModel.getZLevelKey(); - hasSeparateZLevel = hasSeparateZLevel || !!zlevelKey; - (componentType === 'series' ? seriesZLevels : componentZLevels).push({ - zlevel: zlevel, - z: z, - idx: componentModel.componentIndex, - type: componentType, - key: zlevelKey - }); - }); - - if (hasSeparateZLevel) { - // Series after component - var zLevels = componentZLevels.concat(seriesZLevels); - var lastSeriesZLevel_1; - var lastSeriesKey_1; - sort(zLevels, function (a, b) { - if (a.zlevel === b.zlevel) { - return a.z - b.z; - } - - return a.zlevel - b.zlevel; - }); - each$4(zLevels, function (item) { - var componentModel = ecModel.getComponent(item.type, item.idx); - var zlevel = item.zlevel; - var key = item.key; - - if (lastSeriesZLevel_1 != null) { - zlevel = Math.max(lastSeriesZLevel_1, zlevel); - } - - if (key) { - if (zlevel === lastSeriesZLevel_1 && key !== lastSeriesKey_1) { - zlevel++; - } - - lastSeriesKey_1 = key; - } else if (lastSeriesKey_1) { - if (zlevel === lastSeriesZLevel_1) { - zlevel++; - } - - lastSeriesKey_1 = ''; - } - - lastSeriesZLevel_1 = zlevel; - componentModel.setZLevel(zlevel); - }); - } - } - - render = function (ecIns, ecModel, api, payload, updateParams) { - allocateZlevels(ecModel); - renderComponents(ecIns, ecModel, api, payload, updateParams); - each$4(ecIns._chartsViews, function (chart) { - chart.__alive = false; - }); - renderSeries(ecIns, ecModel, api, payload, updateParams); // Remove groups of unrendered charts - - each$4(ecIns._chartsViews, function (chart) { - if (!chart.__alive) { - chart.remove(ecModel, api); - } - }); - }; - - renderComponents = function (ecIns, ecModel, api, payload, updateParams, dirtyList) { - each$4(dirtyList || ecIns._componentsViews, function (componentView) { - var componentModel = componentView.__model; - clearStates(componentModel, componentView); - componentView.render(componentModel, ecModel, api, payload); - updateZ(componentModel, componentView); - updateStates(componentModel, componentView); - }); - }; - /** - * Render each chart and component - */ - - - renderSeries = function (ecIns, ecModel, api, payload, updateParams, dirtyMap) { - // Render all charts - var scheduler = ecIns._scheduler; - updateParams = extend(updateParams || {}, { - updatedSeries: ecModel.getSeries() - }); // TODO progressive? - - lifecycle.trigger('series:beforeupdate', ecModel, api, updateParams); - var unfinished = false; - ecModel.eachSeries(function (seriesModel) { - var chartView = ecIns._chartsMap[seriesModel.__viewId]; - chartView.__alive = true; - var renderTask = chartView.renderTask; - scheduler.updatePayload(renderTask, payload); // TODO states on marker. - - clearStates(seriesModel, chartView); - - if (dirtyMap && dirtyMap.get(seriesModel.uid)) { - renderTask.dirty(); - } - - if (renderTask.perform(scheduler.getPerformArgs(renderTask))) { - unfinished = true; - } - - chartView.group.silent = !!seriesModel.get('silent'); // Should not call markRedraw on group, because it will disable zrender - // incremental render (always render from the __startIndex each frame) - // chartView.group.markRedraw(); - - updateBlend(seriesModel, chartView); - updateSeriesElementSelection(seriesModel); - }); - scheduler.unfinished = unfinished || scheduler.unfinished; - lifecycle.trigger('series:layoutlabels', ecModel, api, updateParams); // transition after label is layouted. - - lifecycle.trigger('series:transition', ecModel, api, updateParams); - ecModel.eachSeries(function (seriesModel) { - var chartView = ecIns._chartsMap[seriesModel.__viewId]; // Update Z after labels updated. Before applying states. - - updateZ(seriesModel, chartView); // NOTE: Update states after label is updated. - // label should be in normal status when layouting. - - updateStates(seriesModel, chartView); - }); // If use hover layer - - updateHoverLayerStatus(ecIns, ecModel); - lifecycle.trigger('series:afterupdate', ecModel, api, updateParams); - }; - - markStatusToUpdate = function (ecIns) { - ecIns[STATUS_NEEDS_UPDATE_KEY] = true; // Wake up zrender if it's sleep. Let it update states in the next frame. - - ecIns.getZr().wakeUp(); - }; - - applyChangedStates = function (ecIns) { - if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) { - return; - } - - ecIns.getZr().storage.traverse(function (el) { - // Not applied on removed elements, it may still in fading. - if (isElementRemoved(el)) { - return; - } - - applyElementStates(el); - }); - ecIns[STATUS_NEEDS_UPDATE_KEY] = false; - }; - - function applyElementStates(el) { - var newStates = []; - var oldStates = el.currentStates; // Keep other states. - - for (var i = 0; i < oldStates.length; i++) { - var stateName = oldStates[i]; - - if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) { - newStates.push(stateName); - } - } // Only use states when it's exists. - - - if (el.selected && el.states.select) { - newStates.push('select'); - } - - if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) { - newStates.push('emphasis'); - } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) { - newStates.push('blur'); - } - - el.useStates(newStates); - } - - function updateHoverLayerStatus(ecIns, ecModel) { - var zr = ecIns._zr; - var storage = zr.storage; - var elCount = 0; - storage.traverse(function (el) { - if (!el.isGroup) { - elCount++; - } - }); - - if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) { - ecModel.eachSeries(function (seriesModel) { - if (seriesModel.preventUsingHoverLayer) { - return; - } - - var chartView = ecIns._chartsMap[seriesModel.__viewId]; - - if (chartView.__alive) { - chartView.eachRendered(function (el) { - if (el.states.emphasis) { - el.states.emphasis.hoverLayer = true; - } - }); - } - }); - } - } - /** - * Update chart and blend. - */ - - - function updateBlend(seriesModel, chartView) { - var blendMode = seriesModel.get('blendMode') || null; - chartView.eachRendered(function (el) { - // FIXME marker and other components - if (!el.isGroup) { - // DON'T mark the element dirty. In case element is incremental and don't want to rerender. - el.style.blend = blendMode; - } - }); - } - - function updateZ(model, view) { - if (model.preventAutoZ) { - return; - } - - var z = model.get('z') || 0; - var zlevel = model.get('zlevel') || 0; // Set z and zlevel - - view.eachRendered(function (el) { - doUpdateZ(el, z, zlevel, -Infinity); // Don't traverse the children because it has been traversed in _updateZ. - - return true; - }); - } - - function doUpdateZ(el, z, zlevel, maxZ2) { - // Group may also have textContent - var label = el.getTextContent(); - var labelLine = el.getTextGuideLine(); - var isGroup = el.isGroup; - - if (isGroup) { - // set z & zlevel of children elements of Group - var children = el.childrenRef(); - - for (var i = 0; i < children.length; i++) { - maxZ2 = Math.max(doUpdateZ(children[i], z, zlevel, maxZ2), maxZ2); - } - } else { - // not Group - el.z = z; - el.zlevel = zlevel; - maxZ2 = Math.max(el.z2, maxZ2); - } // always set z and zlevel if label/labelLine exists - - - if (label) { - label.z = z; - label.zlevel = zlevel; // lift z2 of text content - // TODO if el.emphasis.z2 is spcefied, what about textContent. - - isFinite(maxZ2) && (label.z2 = maxZ2 + 2); - } - - if (labelLine) { - var textGuideLineConfig = el.textGuideLineConfig; - labelLine.z = z; - labelLine.zlevel = zlevel; - isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1)); - } - - return maxZ2; - } // Clear states without animation. - // TODO States on component. - - - function clearStates(model, view) { - view.eachRendered(function (el) { - // Not applied on removed elements, it may still in fading. - if (isElementRemoved(el)) { - return; - } - - var textContent = el.getTextContent(); - var textGuide = el.getTextGuideLine(); - - if (el.stateTransition) { - el.stateTransition = null; - } - - if (textContent && textContent.stateTransition) { - textContent.stateTransition = null; - } - - if (textGuide && textGuide.stateTransition) { - textGuide.stateTransition = null; - } // TODO If el is incremental. - - - if (el.hasState()) { - el.prevStates = el.currentStates; - el.clearStates(); - } else if (el.prevStates) { - el.prevStates = null; - } - }); - } - - function updateStates(model, view) { - var stateAnimationModel = model.getModel('stateAnimation'); - var enableAnimation = model.isAnimationEnabled(); - var duration = stateAnimationModel.get('duration'); - var stateTransition = duration > 0 ? { - duration: duration, - delay: stateAnimationModel.get('delay'), - easing: stateAnimationModel.get('easing') // additive: stateAnimationModel.get('additive') - - } : null; - view.eachRendered(function (el) { - if (el.states && el.states.emphasis) { - // Not applied on removed elements, it may still in fading. - if (isElementRemoved(el)) { - return; - } - - if (el instanceof Path) { - savePathStates(el); - } // Only updated on changed element. In case element is incremental and don't want to rerender. - // TODO, a more proper way? - - - if (el.__dirty) { - var prevStates = el.prevStates; // Restore states without animation - - if (prevStates) { - el.useStates(prevStates); - } - } // Update state transition and enable animation again. - - - if (enableAnimation) { - el.stateTransition = stateTransition; - var textContent = el.getTextContent(); - var textGuide = el.getTextGuideLine(); // TODO Is it necessary to animate label? - - if (textContent) { - textContent.stateTransition = stateTransition; - } - - if (textGuide) { - textGuide.stateTransition = stateTransition; - } - } // Use highlighted and selected flag to toggle states. - - - if (el.__dirty) { - applyElementStates(el); - } - } - }); - } - - createExtensionAPI = function (ecIns) { - return new ( - /** @class */ - function (_super) { - __extends(class_1, _super); - - function class_1() { - return _super !== null && _super.apply(this, arguments) || this; - } - - class_1.prototype.getCoordinateSystems = function () { - return ecIns._coordSysMgr.getCoordinateSystems(); - }; - - class_1.prototype.getComponentByElement = function (el) { - while (el) { - var modelInfo = el.__ecComponentInfo; - - if (modelInfo != null) { - return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index); - } - - el = el.parent; - } - }; - - class_1.prototype.enterEmphasis = function (el, highlightDigit) { - enterEmphasis(el, highlightDigit); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.leaveEmphasis = function (el, highlightDigit) { - leaveEmphasis(el, highlightDigit); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.enterBlur = function (el) { - enterBlur(el); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.leaveBlur = function (el) { - leaveBlur(el); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.enterSelect = function (el) { - enterSelect(el); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.leaveSelect = function (el) { - leaveSelect(el); - markStatusToUpdate(ecIns); - }; - - class_1.prototype.getModel = function () { - return ecIns.getModel(); - }; - - class_1.prototype.getViewOfComponentModel = function (componentModel) { - return ecIns.getViewOfComponentModel(componentModel); - }; - - class_1.prototype.getViewOfSeriesModel = function (seriesModel) { - return ecIns.getViewOfSeriesModel(seriesModel); - }; - - return class_1; - }(ExtensionAPI))(ecIns); - }; - - enableConnect = function (chart) { - function updateConnectedChartsStatus(charts, status) { - for (var i = 0; i < charts.length; i++) { - var otherChart = charts[i]; - otherChart[CONNECT_STATUS_KEY] = status; - } - } - - each$4(eventActionMap, function (actionType, eventType) { - chart._messageCenter.on(eventType, function (event) { - if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) { - if (event && event.escapeConnect) { - return; - } - - var action_1 = chart.makeActionFromEvent(event); - var otherCharts_1 = []; - each$4(instances, function (otherChart) { - if (otherChart !== chart && otherChart.group === chart.group) { - otherCharts_1.push(otherChart); - } - }); - updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING); - each$4(otherCharts_1, function (otherChart) { - if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) { - otherChart.dispatchAction(action_1); - } - }); - updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED); - } - }); - }); - }; - }(); - - return ECharts; - }(Eventful); - - var echartsProto = ECharts.prototype; - echartsProto.on = createRegisterEventWithLowercaseECharts('on'); - echartsProto.off = createRegisterEventWithLowercaseECharts('off'); - /** - * @deprecated - */ - // @ts-ignore - - echartsProto.one = function (eventName, cb, ctx) { - var self = this; - deprecateLog('ECharts#one is deprecated.'); - - function wrapped() { - var args2 = []; - - for (var _i = 0; _i < arguments.length; _i++) { - args2[_i] = arguments[_i]; - } - - cb && cb.apply && cb.apply(this, args2); // @ts-ignore - - self.off(eventName, wrapped); - } // @ts-ignore - - - this.on.call(this, eventName, wrapped, ctx); - }; - - var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu']; - - function disposedWarning(id) { - { - warn('Instance ' + id + ' has been disposed'); - } - } - - var actions = {}; - /** - * Map eventType to actionType - */ - - var eventActionMap = {}; - var dataProcessorFuncs = []; - var optionPreprocessorFuncs = []; - var visualFuncs = []; - var themeStorage = {}; - var loadingEffects = {}; - var instances = {}; - var connectedGroups = {}; - var idBase = +new Date() - 0; - var groupIdBase = +new Date() - 0; - var DOM_ATTRIBUTE_KEY = '_echarts_instance_'; - /** - * @param opts.devicePixelRatio Use window.devicePixelRatio by default - * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart. - * @param opts.width Use clientWidth of the input `dom` by default. - * Can be 'auto' (the same as null/undefined) - * @param opts.height Use clientHeight of the input `dom` by default. - * Can be 'auto' (the same as null/undefined) - * @param opts.locale Specify the locale. - * @param opts.useDirtyRect Enable dirty rectangle rendering or not. - */ - - function init(dom, theme, opts) { - var isClient = !(opts && opts.ssr); - - if (isClient) { - { - if (!dom) { - throw new Error('Initialize failed: invalid dom.'); - } - } - var existInstance = getInstanceByDom(dom); - - if (existInstance) { - { - warn('There is a chart instance already initialized on the dom.'); - } - return existInstance; - } - - { - if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) { - warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.'); - } - } - } - - var chart = new ECharts(dom, theme, opts); - chart.id = 'ec_' + idBase++; - instances[chart.id] = chart; - isClient && setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id); - enableConnect(chart); - lifecycle.trigger('afterinit', chart); - return chart; - } - /** - * @usage - * (A) - * ```js - * let chart1 = echarts.init(dom1); - * let chart2 = echarts.init(dom2); - * chart1.group = 'xxx'; - * chart2.group = 'xxx'; - * echarts.connect('xxx'); - * ``` - * (B) - * ```js - * let chart1 = echarts.init(dom1); - * let chart2 = echarts.init(dom2); - * echarts.connect('xxx', [chart1, chart2]); - * ``` - */ - - - function connect(groupId) { - // Is array of charts - if (isArray(groupId)) { - var charts = groupId; - groupId = null; // If any chart has group - - each$4(charts, function (chart) { - if (chart.group != null) { - groupId = chart.group; - } - }); - groupId = groupId || 'g_' + groupIdBase++; - each$4(charts, function (chart) { - chart.group = groupId; - }); - } - - connectedGroups[groupId] = true; - return groupId; - } - - function disconnect(groupId) { - connectedGroups[groupId] = false; - } - /** - * Alias and backward compatibility - * @deprecated - */ - - - var disConnect = disconnect; - /** - * Dispose a chart instance - */ - - function dispose(chart) { - if (isString(chart)) { - chart = instances[chart]; - } else if (!(chart instanceof ECharts)) { - // Try to treat as dom - chart = getInstanceByDom(chart); - } - - if (chart instanceof ECharts && !chart.isDisposed()) { - chart.dispose(); - } - } - - function getInstanceByDom(dom) { - return instances[getAttribute(dom, DOM_ATTRIBUTE_KEY)]; - } - - function getInstanceById(key) { - return instances[key]; - } - /** - * Register theme - */ - - - function registerTheme(name, theme) { - themeStorage[name] = theme; - } - /** - * Register option preprocessor - */ - - - function registerPreprocessor(preprocessorFunc) { - if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) { - optionPreprocessorFuncs.push(preprocessorFunc); - } - } - - function registerProcessor(priority, processor) { - normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT); - } - /** - * Register postIniter - * @param {Function} postInitFunc - */ - - - function registerPostInit(postInitFunc) { - registerUpdateLifecycle('afterinit', postInitFunc); - } - /** - * Register postUpdater - * @param {Function} postUpdateFunc - */ - - - function registerPostUpdate(postUpdateFunc) { - registerUpdateLifecycle('afterupdate', postUpdateFunc); - } - - function registerUpdateLifecycle(name, cb) { - lifecycle.on(name, cb); - } - - function registerAction(actionInfo, eventName, action) { - if (isFunction(eventName)) { - action = eventName; - eventName = ''; - } - - var actionType = isObject$2(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = { - event: eventName - }][0]; // Event name is all lowercase - - actionInfo.event = (actionInfo.event || actionType).toLowerCase(); - eventName = actionInfo.event; - - if (eventActionMap[eventName]) { - // Already registered. - return; - } // Validate action type and event name. - - - assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName)); - - if (!actions[actionType]) { - actions[actionType] = { - action: action, - actionInfo: actionInfo - }; - } - - eventActionMap[eventName] = actionType; - } - - function registerCoordinateSystem(type, coordSysCreator) { - CoordinateSystemManager.register(type, coordSysCreator); - } - /** - * Get dimensions of specified coordinate system. - * @param {string} type - * @return {Array.} - */ - - - function getCoordinateSystemDimensions(type) { - var coordSysCreator = CoordinateSystemManager.get(type); - - if (coordSysCreator) { - return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice(); - } - } - - function registerLayout(priority, layoutTask) { - normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout'); - } - - function registerVisual(priority, visualTask) { - normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual'); - } - - var registeredTasks = []; - - function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) { - if (isFunction(priority) || isObject$2(priority)) { - fn = priority; - priority = defaultPriority; - } - - { - if (isNaN(priority) || priority == null) { - throw new Error('Illegal priority'); - } // Check duplicate - - - each$4(targetList, function (wrap) { - assert(wrap.__raw !== fn); - }); - } // Already registered - - if (indexOf(registeredTasks, fn) >= 0) { - return; - } - - registeredTasks.push(fn); - var stageHandler = Scheduler.wrapStageHandler(fn, visualType); - stageHandler.__prio = priority; - stageHandler.__raw = fn; - targetList.push(stageHandler); - } - - function registerLoading(name, loadingFx) { - loadingEffects[name] = loadingFx; - } - /** - * ZRender need a canvas context to do measureText. - * But in node environment canvas may be created by node-canvas. - * So we need to specify how to create a canvas instead of using document.createElement('canvas') - * - * - * @deprecated use setPlatformAPI({ createCanvas }) instead. - * - * @example - * let Canvas = require('canvas'); - * let echarts = require('echarts'); - * echarts.setCanvasCreator(function () { - * // Small size is enough. - * return new Canvas(32, 32); - * }); - */ - - - function setCanvasCreator(creator) { - { - deprecateLog('setCanvasCreator is deprecated. Use setPlatformAPI({ createCanvas }) instead.'); - } - setPlatformAPI({ - createCanvas: creator - }); - } - /** - * The parameters and usage: see `geoSourceManager.registerMap`. - * Compatible with previous `echarts.registerMap`. - */ - - - function registerMap(mapName, geoJson, specialAreas) { - var registerMap = getImpl('registerMap'); - registerMap && registerMap(mapName, geoJson, specialAreas); - } - - function getMap(mapName) { - var getMap = getImpl('getMap'); - return getMap && getMap(mapName); - } - - var registerTransform = registerExternalTransform; - /** - * Globa dispatchAction to a specified chart instance. - */ - // export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters[1]) { - // if (!payload || !payload.chartId) { - // // Must have chartId to find chart - // return; - // } - // const chart = instances[payload.chartId]; - // if (chart) { - // chart.dispatchAction(payload, opt); - // } - // } - // Builtin global visual - - registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask); - registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask); - registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask); - registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask); - registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask); - registerVisual(PRIORITY_VISUAL_DECAL, decalVisual); - registerPreprocessor(globalBackwardCompat); - registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack$1); - registerLoading('default', defaultLoading); // Default actions - - registerAction({ - type: HIGHLIGHT_ACTION_TYPE, - event: HIGHLIGHT_ACTION_TYPE, - update: HIGHLIGHT_ACTION_TYPE - }, noop); - registerAction({ - type: DOWNPLAY_ACTION_TYPE, - event: DOWNPLAY_ACTION_TYPE, - update: DOWNPLAY_ACTION_TYPE - }, noop); - registerAction({ - type: SELECT_ACTION_TYPE, - event: SELECT_ACTION_TYPE, - update: SELECT_ACTION_TYPE - }, noop); - registerAction({ - type: UNSELECT_ACTION_TYPE, - event: UNSELECT_ACTION_TYPE, - update: UNSELECT_ACTION_TYPE - }, noop); - registerAction({ - type: TOGGLE_SELECT_ACTION_TYPE, - event: TOGGLE_SELECT_ACTION_TYPE, - update: TOGGLE_SELECT_ACTION_TYPE - }, noop); // Default theme - - registerTheme('light', lightTheme); - registerTheme('dark', theme); // For backward compatibility, where the namespace `dataTool` will - // be mounted on `echarts` is the extension `dataTool` is imported. - - var dataTool = {}; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - function dataIndexMapValueLength(valNumOrArrLengthMoreThan2) { - return valNumOrArrLengthMoreThan2 == null ? 0 : valNumOrArrLengthMoreThan2.length || 1; - } - - function defaultKeyGetter(item) { - return item; - } - - var DataDiffer = - /** @class */ - function () { - /** - * @param context Can be visited by this.context in callback. - */ - function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context, // By default: 'oneToOne'. - diffMode) { - this._old = oldArr; - this._new = newArr; - this._oldKeyGetter = oldKeyGetter || defaultKeyGetter; - this._newKeyGetter = newKeyGetter || defaultKeyGetter; // Visible in callback via `this.context`; - - this.context = context; - this._diffModeMultiple = diffMode === 'multiple'; - } - /** - * Callback function when add a data - */ - - - DataDiffer.prototype.add = function (func) { - this._add = func; - return this; - }; - /** - * Callback function when update a data - */ - - - DataDiffer.prototype.update = function (func) { - this._update = func; - return this; - }; - /** - * Callback function when update a data and only work in `cbMode: 'byKey'`. - */ - - - DataDiffer.prototype.updateManyToOne = function (func) { - this._updateManyToOne = func; - return this; - }; - /** - * Callback function when update a data and only work in `cbMode: 'byKey'`. - */ - - - DataDiffer.prototype.updateOneToMany = function (func) { - this._updateOneToMany = func; - return this; - }; - /** - * Callback function when update a data and only work in `cbMode: 'byKey'`. - */ - - - DataDiffer.prototype.updateManyToMany = function (func) { - this._updateManyToMany = func; - return this; - }; - /** - * Callback function when remove a data - */ - - - DataDiffer.prototype.remove = function (func) { - this._remove = func; - return this; - }; - - DataDiffer.prototype.execute = function () { - this[this._diffModeMultiple ? '_executeMultiple' : '_executeOneToOne'](); - }; - - DataDiffer.prototype._executeOneToOne = function () { - var oldArr = this._old; - var newArr = this._new; - var newDataIndexMap = {}; - var oldDataKeyArr = new Array(oldArr.length); - var newDataKeyArr = new Array(newArr.length); - - this._initIndexMap(oldArr, null, oldDataKeyArr, '_oldKeyGetter'); - - this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); - - for (var i = 0; i < oldArr.length; i++) { - var oldKey = oldDataKeyArr[i]; - var newIdxMapVal = newDataIndexMap[oldKey]; - var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); // idx can never be empty array here. see 'set null' logic below. - - if (newIdxMapValLen > 1) { - // Consider there is duplicate key (for example, use dataItem.name as key). - // We should make sure every item in newArr and oldArr can be visited. - var newIdx = newIdxMapVal.shift(); - - if (newIdxMapVal.length === 1) { - newDataIndexMap[oldKey] = newIdxMapVal[0]; - } - - this._update && this._update(newIdx, i); - } else if (newIdxMapValLen === 1) { - newDataIndexMap[oldKey] = null; - this._update && this._update(newIdxMapVal, i); - } else { - this._remove && this._remove(i); - } - } - - this._performRestAdd(newDataKeyArr, newDataIndexMap); - }; - /** - * For example, consider the case: - * oldData: [o0, o1, o2, o3, o4, o5, o6, o7], - * newData: [n0, n1, n2, n3, n4, n5, n6, n7, n8], - * Where: - * o0, o1, n0 has key 'a' (many to one) - * o5, n4, n5, n6 has key 'b' (one to many) - * o2, n1 has key 'c' (one to one) - * n2, n3 has key 'd' (add) - * o3, o4 has key 'e' (remove) - * o6, o7, n7, n8 has key 'f' (many to many, treated as add and remove) - * Then: - * (The order of the following directives are not ensured.) - * this._updateManyToOne(n0, [o0, o1]); - * this._updateOneToMany([n4, n5, n6], o5); - * this._update(n1, o2); - * this._remove(o3); - * this._remove(o4); - * this._remove(o6); - * this._remove(o7); - * this._add(n2); - * this._add(n3); - * this._add(n7); - * this._add(n8); - */ - - - DataDiffer.prototype._executeMultiple = function () { - var oldArr = this._old; - var newArr = this._new; - var oldDataIndexMap = {}; - var newDataIndexMap = {}; - var oldDataKeyArr = []; - var newDataKeyArr = []; - - this._initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter'); - - this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); - - for (var i = 0; i < oldDataKeyArr.length; i++) { - var oldKey = oldDataKeyArr[i]; - var oldIdxMapVal = oldDataIndexMap[oldKey]; - var newIdxMapVal = newDataIndexMap[oldKey]; - var oldIdxMapValLen = dataIndexMapValueLength(oldIdxMapVal); - var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); - - if (oldIdxMapValLen > 1 && newIdxMapValLen === 1) { - this._updateManyToOne && this._updateManyToOne(newIdxMapVal, oldIdxMapVal); - newDataIndexMap[oldKey] = null; - } else if (oldIdxMapValLen === 1 && newIdxMapValLen > 1) { - this._updateOneToMany && this._updateOneToMany(newIdxMapVal, oldIdxMapVal); - newDataIndexMap[oldKey] = null; - } else if (oldIdxMapValLen === 1 && newIdxMapValLen === 1) { - this._update && this._update(newIdxMapVal, oldIdxMapVal); - newDataIndexMap[oldKey] = null; - } else if (oldIdxMapValLen > 1 && newIdxMapValLen > 1) { - this._updateManyToMany && this._updateManyToMany(newIdxMapVal, oldIdxMapVal); - newDataIndexMap[oldKey] = null; - } else if (oldIdxMapValLen > 1) { - for (var i_1 = 0; i_1 < oldIdxMapValLen; i_1++) { - this._remove && this._remove(oldIdxMapVal[i_1]); - } - } else { - this._remove && this._remove(oldIdxMapVal); - } - } - - this._performRestAdd(newDataKeyArr, newDataIndexMap); - }; - - DataDiffer.prototype._performRestAdd = function (newDataKeyArr, newDataIndexMap) { - for (var i = 0; i < newDataKeyArr.length; i++) { - var newKey = newDataKeyArr[i]; - var newIdxMapVal = newDataIndexMap[newKey]; - var idxMapValLen = dataIndexMapValueLength(newIdxMapVal); - - if (idxMapValLen > 1) { - for (var j = 0; j < idxMapValLen; j++) { - this._add && this._add(newIdxMapVal[j]); - } - } else if (idxMapValLen === 1) { - this._add && this._add(newIdxMapVal); - } // Support both `newDataKeyArr` are duplication removed or not removed. - - - newDataIndexMap[newKey] = null; - } - }; - - DataDiffer.prototype._initIndexMap = function (arr, // Can be null. - map, // In 'byKey', the output `keyArr` is duplication removed. - // In 'byIndex', the output `keyArr` is not duplication removed and - // its indices are accurately corresponding to `arr`. - keyArr, keyGetterName) { - var cbModeMultiple = this._diffModeMultiple; - - for (var i = 0; i < arr.length; i++) { - // Add prefix to avoid conflict with Object.prototype. - var key = '_ec_' + this[keyGetterName](arr[i], i); - - if (!cbModeMultiple) { - keyArr[i] = key; - } - - if (!map) { - continue; - } - - var idxMapVal = map[key]; - var idxMapValLen = dataIndexMapValueLength(idxMapVal); - - if (idxMapValLen === 0) { - // Simple optimize: in most cases, one index has one key, - // do not need array. - map[key] = i; - - if (cbModeMultiple) { - keyArr.push(key); - } - } else if (idxMapValLen === 1) { - map[key] = [idxMapVal, i]; - } else { - idxMapVal.push(i); - } - } - }; - - return DataDiffer; - }(); - - var DimensionUserOuput = - /** @class */ - function () { - function DimensionUserOuput(encode, dimRequest) { - this._encode = encode; - this._schema = dimRequest; - } - - DimensionUserOuput.prototype.get = function () { - return { - // Do not generate full dimension name until fist used. - fullDimensions: this._getFullDimensionNames(), - encode: this._encode - }; - }; - /** - * Get all data store dimension names. - * Theoretically a series data store is defined both by series and used dataset (if any). - * If some dimensions are omitted for performance reason in `this.dimensions`, - * the dimension name may not be auto-generated if user does not specify a dimension name. - * In this case, the dimension name is `null`/`undefined`. - */ - - - DimensionUserOuput.prototype._getFullDimensionNames = function () { - if (!this._cachedDimNames) { - this._cachedDimNames = this._schema ? this._schema.makeOutputDimensionNames() : []; - } - - return this._cachedDimNames; - }; - - return DimensionUserOuput; - }(); - - function summarizeDimensions(data, schema) { - var summary = {}; - var encode = summary.encode = {}; - var notExtraCoordDimMap = createHashMap(); - var defaultedLabel = []; - var defaultedTooltip = []; - var userOutputEncode = {}; - each$4(data.dimensions, function (dimName) { - var dimItem = data.getDimensionInfo(dimName); - var coordDim = dimItem.coordDim; - - if (coordDim) { - { - assert(VISUAL_DIMENSIONS.get(coordDim) == null); - } - var coordDimIndex = dimItem.coordDimIndex; - getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName; - - if (!dimItem.isExtraCoord) { - notExtraCoordDimMap.set(coordDim, 1); // Use the last coord dim (and label friendly) as default label, - // because when dataset is used, it is hard to guess which dimension - // can be value dimension. If both show x, y on label is not look good, - // and conventionally y axis is focused more. - - if (mayLabelDimType(dimItem.type)) { - defaultedLabel[0] = dimName; - } // User output encode do not contain generated coords. - // And it only has index. User can use index to retrieve value from the raw item array. - - - getOrCreateEncodeArr(userOutputEncode, coordDim)[coordDimIndex] = data.getDimensionIndex(dimItem.name); - } - - if (dimItem.defaultTooltip) { - defaultedTooltip.push(dimName); - } - } - - VISUAL_DIMENSIONS.each(function (v, otherDim) { - var encodeArr = getOrCreateEncodeArr(encode, otherDim); - var dimIndex = dimItem.otherDims[otherDim]; - - if (dimIndex != null && dimIndex !== false) { - encodeArr[dimIndex] = dimItem.name; - } - }); - }); - var dataDimsOnCoord = []; - var encodeFirstDimNotExtra = {}; - notExtraCoordDimMap.each(function (v, coordDim) { - var dimArr = encode[coordDim]; - encodeFirstDimNotExtra[coordDim] = dimArr[0]; // Not necessary to remove duplicate, because a data - // dim canot on more than one coordDim. - - dataDimsOnCoord = dataDimsOnCoord.concat(dimArr); - }); - summary.dataDimsOnCoord = dataDimsOnCoord; - summary.dataDimIndicesOnCoord = map$1(dataDimsOnCoord, function (dimName) { - return data.getDimensionInfo(dimName).storeDimIndex; - }); - summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra; - var encodeLabel = encode.label; // FIXME `encode.label` is not recommended, because formatter cannot be set - // in this way. Use label.formatter instead. Maybe remove this approach someday. - - if (encodeLabel && encodeLabel.length) { - defaultedLabel = encodeLabel.slice(); - } - - var encodeTooltip = encode.tooltip; - - if (encodeTooltip && encodeTooltip.length) { - defaultedTooltip = encodeTooltip.slice(); - } else if (!defaultedTooltip.length) { - defaultedTooltip = defaultedLabel.slice(); - } - - encode.defaultedLabel = defaultedLabel; - encode.defaultedTooltip = defaultedTooltip; - summary.userOutput = new DimensionUserOuput(userOutputEncode, schema); - return summary; - } - - function getOrCreateEncodeArr(encode, dim) { - if (!encode.hasOwnProperty(dim)) { - encode[dim] = []; - } - - return encode[dim]; - } // FIXME:TS should be type `AxisType` - - - function getDimensionTypeByAxis(axisType) { - return axisType === 'category' ? 'ordinal' : axisType === 'time' ? 'time' : 'float'; - } - - function mayLabelDimType(dimType) { - // In most cases, ordinal and time do not suitable for label. - // Ordinal info can be displayed on axis. Time is too long. - return !(dimType === 'ordinal' || dimType === 'time'); - } // function findTheLastDimMayLabel(data) { - // // Get last value dim - // let dimensions = data.dimensions.slice(); - // let valueType; - // let valueDim; - // while (dimensions.length && ( - // valueDim = dimensions.pop(), - // valueType = data.getDimensionInfo(valueDim).type, - // valueType === 'ordinal' || valueType === 'time' - // )) {} // jshint ignore:line - // return valueDim; - // } - - - var SeriesDimensionDefine = - /** @class */ - function () { - /** - * @param opt All of the fields will be shallow copied. - */ - function SeriesDimensionDefine(opt) { - /** - * The format of `otherDims` is: - * ```js - * { - * tooltip?: number - * label?: number - * itemName?: number - * seriesName?: number - * } - * ``` - * - * A `series.encode` can specified these fields: - * ```js - * encode: { - * // "3, 1, 5" is the index of data dimension. - * tooltip: [3, 1, 5], - * label: [0, 3], - * ... - * } - * ``` - * `otherDims` is the parse result of the `series.encode` above, like: - * ```js - * // Suppose the index of this data dimension is `3`. - * this.otherDims = { - * // `3` is at the index `0` of the `encode.tooltip` - * tooltip: 0, - * // `3` is at the index `1` of the `encode.label` - * label: 1 - * }; - * ``` - * - * This prop should never be `null`/`undefined` after initialized. - */ - this.otherDims = {}; - - if (opt != null) { - extend(this, opt); - } - } - - return SeriesDimensionDefine; - }(); - - var inner$5 = makeInner(); - var dimTypeShort = { - float: 'f', - int: 'i', - ordinal: 'o', - number: 'n', - time: 't' - }; - /** - * Represents the dimension requirement of a series. - * - * NOTICE: - * When there are too many dimensions in dataset and many series, only the used dimensions - * (i.e., used by coord sys and declared in `series.encode`) are add to `dimensionDefineList`. - * But users may query data by other unused dimension names. - * In this case, users can only query data if and only if they have defined dimension names - * via ec option, so we provide `getDimensionIndexFromSource`, which only query them from - * `source` dimensions. - */ - - var SeriesDataSchema = - /** @class */ - function () { - function SeriesDataSchema(opt) { - this.dimensions = opt.dimensions; - this._dimOmitted = opt.dimensionOmitted; - this.source = opt.source; - this._fullDimCount = opt.fullDimensionCount; - - this._updateDimOmitted(opt.dimensionOmitted); - } - - SeriesDataSchema.prototype.isDimensionOmitted = function () { - return this._dimOmitted; - }; - - SeriesDataSchema.prototype._updateDimOmitted = function (dimensionOmitted) { - this._dimOmitted = dimensionOmitted; - - if (!dimensionOmitted) { - return; - } - - if (!this._dimNameMap) { - this._dimNameMap = ensureSourceDimNameMap(this.source); - } - }; - /** - * @caution Can only be used when `dimensionOmitted: true`. - * - * Get index by user defined dimension name (i.e., not internal generate name). - * That is, get index from `dimensionsDefine`. - * If no `dimensionsDefine`, or no name get, return -1. - */ - - - SeriesDataSchema.prototype.getSourceDimensionIndex = function (dimName) { - return retrieve2(this._dimNameMap.get(dimName), -1); - }; - /** - * @caution Can only be used when `dimensionOmitted: true`. - * - * Notice: may return `null`/`undefined` if user not specify dimension names. - */ - - - SeriesDataSchema.prototype.getSourceDimension = function (dimIndex) { - var dimensionsDefine = this.source.dimensionsDefine; - - if (dimensionsDefine) { - return dimensionsDefine[dimIndex]; - } - }; - - SeriesDataSchema.prototype.makeStoreSchema = function () { - var dimCount = this._fullDimCount; - var willRetrieveDataByName = shouldRetrieveDataByName(this.source); - var makeHashStrict = !shouldOmitUnusedDimensions(dimCount); // If source don't have dimensions or series don't omit unsed dimensions. - // Generate from seriesDimList directly - - var dimHash = ''; - var dims = []; - - for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < dimCount; fullDimIdx++) { - var property = void 0; - var type = void 0; - var ordinalMeta = void 0; - var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc. - - if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) { - property = willRetrieveDataByName ? seriesDimDef.name : null; - type = seriesDimDef.type; - ordinalMeta = seriesDimDef.ordinalMeta; - seriesDimIdx++; - } else { - var sourceDimDef = this.getSourceDimension(fullDimIdx); - - if (sourceDimDef) { - property = willRetrieveDataByName ? sourceDimDef.name : null; - type = sourceDimDef.type; - } - } - - dims.push({ - property: property, - type: type, - ordinalMeta: ordinalMeta - }); // If retrieving data by index, - // use to determine whether data can be shared. - // (Because in this case there might be no dimension name defined in dataset, but indices always exists). - // (Indices are always 0, 1, 2, ..., so we can ignore them to shorten the hash). - // Otherwise if retrieving data by property name (like `data: [{aa: 123, bb: 765}, ...]`), - // use in hash. - - if (willRetrieveDataByName && property != null // For data stack, we have make sure each series has its own dim on this store. - // So we do not add property to hash to make sure they can share this store. - && (!seriesDimDef || !seriesDimDef.isCalculationCoord)) { - dimHash += makeHashStrict // Use escape character '`' in case that property name contains '$'. - ? property.replace(/\`/g, '`1').replace(/\$/g, '`2') // For better performance, when there are large dimensions, tolerant this defects that hardly meet. - : property; - } - - dimHash += '$'; - dimHash += dimTypeShort[type] || 'f'; - - if (ordinalMeta) { - dimHash += ordinalMeta.uid; - } - - dimHash += '$'; - } // Source from endpoint(usually series) will be read differently - // when seriesLayoutBy or startIndex(which is affected by sourceHeader) are different. - // So we use this three props as key. - - - var source = this.source; - var hash = [source.seriesLayoutBy, source.startIndex, dimHash].join('$$'); - return { - dimensions: dims, - hash: hash - }; - }; - - SeriesDataSchema.prototype.makeOutputDimensionNames = function () { - var result = []; - - for (var fullDimIdx = 0, seriesDimIdx = 0; fullDimIdx < this._fullDimCount; fullDimIdx++) { - var name_1 = void 0; - var seriesDimDef = this.dimensions[seriesDimIdx]; // The list has been sorted by `storeDimIndex` asc. - - if (seriesDimDef && seriesDimDef.storeDimIndex === fullDimIdx) { - if (!seriesDimDef.isCalculationCoord) { - name_1 = seriesDimDef.name; - } - - seriesDimIdx++; - } else { - var sourceDimDef = this.getSourceDimension(fullDimIdx); - - if (sourceDimDef) { - name_1 = sourceDimDef.name; - } - } - - result.push(name_1); - } - - return result; - }; - - SeriesDataSchema.prototype.appendCalculationDimension = function (dimDef) { - this.dimensions.push(dimDef); - dimDef.isCalculationCoord = true; - this._fullDimCount++; // If append dimension on a data store, consider the store - // might be shared by different series, series dimensions not - // really map to store dimensions. - - this._updateDimOmitted(true); - }; - - return SeriesDataSchema; - }(); - - function isSeriesDataSchema(schema) { - return schema instanceof SeriesDataSchema; - } - - function createDimNameMap(dimsDef) { - var dataDimNameMap = createHashMap(); - - for (var i = 0; i < (dimsDef || []).length; i++) { - var dimDefItemRaw = dimsDef[i]; - var userDimName = isObject$2(dimDefItemRaw) ? dimDefItemRaw.name : dimDefItemRaw; - - if (userDimName != null && dataDimNameMap.get(userDimName) == null) { - dataDimNameMap.set(userDimName, i); - } - } - - return dataDimNameMap; - } - - function ensureSourceDimNameMap(source) { - var innerSource = inner$5(source); - return innerSource.dimNameMap || (innerSource.dimNameMap = createDimNameMap(source.dimensionsDefine)); - } - - function shouldOmitUnusedDimensions(dimCount) { - return dimCount > 30; - } - - var isObject = isObject$2; - var map = map$1; - var CtorInt32Array = typeof Int32Array === 'undefined' ? Array : Int32Array; // Use prefix to avoid index to be the same as otherIdList[idx], - // which will cause weird update animation. - - var ID_PREFIX = 'e\0\0'; - var INDEX_NOT_FOUND = -1; // type SeriesDimensionIndex = DimensionIndex; - - var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_dimSummary', 'userOutput', '_rawData', '_dimValueGetter', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount']; - var CLONE_PROPERTIES = ['_approximateExtent']; // ----------------------------- - // Internal method declarations: - // ----------------------------- - - var prepareInvertedIndex; - var getId; - var getIdNameFromStore; - var normalizeDimensions; - var transferProperties; - var cloneListForMapAndSample; - var makeIdFromName; - - var SeriesData = - /** @class */ - function () { - /** - * @param dimensionsInput.dimensions - * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...]. - * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius - */ - function SeriesData(dimensionsInput, hostModel) { - this.type = 'list'; - this._dimOmitted = false; - this._nameList = []; - this._idList = []; // Models of data option is stored sparse for optimizing memory cost - // Never used yet (not used yet). - // private _optionModels: Model[] = []; - // Global visual properties after visual coding - - this._visual = {}; // Global layout properties. - - this._layout = {}; // Item visual properties after visual coding - - this._itemVisuals = []; // Item layout properties after layout - - this._itemLayouts = []; // Graphic elements - - this._graphicEls = []; // key: dim, value: extent - - this._approximateExtent = {}; - this._calculationInfo = {}; // Having detected that there is data item is non primitive type - // (in type `OptionDataItemObject`). - // Like `data: [ { value: xx, itemStyle: {...} }, ...]` - // At present it only happen in `SOURCE_FORMAT_ORIGINAL`. - - this.hasItemOption = false; // Methods that create a new list based on this list should be listed here. - // Notice that those method should `RETURN` the new list. - - this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map']; // Methods that change indices of this list should be listed here. - - this.CHANGABLE_METHODS = ['filterSelf', 'selectRange']; - this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample']; - var dimensions; - var assignStoreDimIdx = false; - - if (isSeriesDataSchema(dimensionsInput)) { - dimensions = dimensionsInput.dimensions; - this._dimOmitted = dimensionsInput.isDimensionOmitted(); - this._schema = dimensionsInput; - } else { - assignStoreDimIdx = true; - dimensions = dimensionsInput; - } - - dimensions = dimensions || ['x', 'y']; - var dimensionInfos = {}; - var dimensionNames = []; - var invertedIndicesMap = {}; - var needsHasOwn = false; - var emptyObj = {}; - - for (var i = 0; i < dimensions.length; i++) { - // Use the original dimensions[i], where other flag props may exists. - var dimInfoInput = dimensions[i]; - var dimensionInfo = isString(dimInfoInput) ? new SeriesDimensionDefine({ - name: dimInfoInput - }) : !(dimInfoInput instanceof SeriesDimensionDefine) ? new SeriesDimensionDefine(dimInfoInput) : dimInfoInput; - var dimensionName = dimensionInfo.name; - dimensionInfo.type = dimensionInfo.type || 'float'; - - if (!dimensionInfo.coordDim) { - dimensionInfo.coordDim = dimensionName; - dimensionInfo.coordDimIndex = 0; - } - - var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {}; - dimensionNames.push(dimensionName); - dimensionInfos[dimensionName] = dimensionInfo; - - if (emptyObj[dimensionName] != null) { - needsHasOwn = true; - } - - if (dimensionInfo.createInvertedIndices) { - invertedIndicesMap[dimensionName] = []; - } - - if (otherDims.itemName === 0) { - this._nameDimIdx = i; - } - - if (otherDims.itemId === 0) { - this._idDimIdx = i; - } - - { - assert(assignStoreDimIdx || dimensionInfo.storeDimIndex >= 0); - } - - if (assignStoreDimIdx) { - dimensionInfo.storeDimIndex = i; - } - } - - this.dimensions = dimensionNames; - this._dimInfos = dimensionInfos; - - this._initGetDimensionInfo(needsHasOwn); - - this.hostModel = hostModel; - this._invertedIndicesMap = invertedIndicesMap; - - if (this._dimOmitted) { - var dimIdxToName_1 = this._dimIdxToName = createHashMap(); - each$4(dimensionNames, function (dimName) { - dimIdxToName_1.set(dimensionInfos[dimName].storeDimIndex, dimName); - }); - } - } - /** - * - * Get concrete dimension name by dimension name or dimension index. - * If input a dimension name, do not validate whether the dimension name exits. - * - * @caution - * @param dim Must make sure the dimension is `SeriesDimensionLoose`. - * Because only those dimensions will have auto-generated dimension names if not - * have a user-specified name, and other dimensions will get a return of null/undefined. - * - * @notice Because of this reason, should better use `getDimensionIndex` instead, for examples: - * ```js - * const val = data.getStore().get(data.getDimensionIndex(dim), dataIdx); - * ``` - * - * @return Concrete dim name. - */ - - - SeriesData.prototype.getDimension = function (dim) { - var dimIdx = this._recognizeDimIndex(dim); - - if (dimIdx == null) { - return dim; - } - - dimIdx = dim; - - if (!this._dimOmitted) { - return this.dimensions[dimIdx]; - } // Retrieve from series dimension definition because it probably contains - // generated dimension name (like 'x', 'y'). - - - var dimName = this._dimIdxToName.get(dimIdx); - - if (dimName != null) { - return dimName; - } - - var sourceDimDef = this._schema.getSourceDimension(dimIdx); - - if (sourceDimDef) { - return sourceDimDef.name; - } - }; - /** - * Get dimension index in data store. Return -1 if not found. - * Can be used to index value from getRawValue. - */ - - - SeriesData.prototype.getDimensionIndex = function (dim) { - var dimIdx = this._recognizeDimIndex(dim); - - if (dimIdx != null) { - return dimIdx; - } - - if (dim == null) { - return -1; - } - - var dimInfo = this._getDimInfo(dim); - - return dimInfo ? dimInfo.storeDimIndex : this._dimOmitted ? this._schema.getSourceDimensionIndex(dim) : -1; - }; - /** - * The meanings of the input parameter `dim`: - * - * + If dim is a number (e.g., `1`), it means the index of the dimension. - * For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'. - * + If dim is a number-like string (e.g., `"1"`): - * + If there is the same concrete dim name defined in `series.dimensions` or `dataset.dimensions`, - * it means that concrete name. - * + If not, it will be converted to a number, which means the index of the dimension. - * (why? because of the backward compatibility. We have been tolerating number-like string in - * dimension setting, although now it seems that it is not a good idea.) - * For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`, - * if no dimension name is defined as `"1"`. - * + If dim is a not-number-like string, it means the concrete dim name. - * For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`, - * or customized in `dimensions` property of option like `"age"`. - * - * @return recognized `DimensionIndex`. Otherwise return null/undefined (means that dim is `DimensionName`). - */ - - - SeriesData.prototype._recognizeDimIndex = function (dim) { - if (isNumber(dim) // If being a number-like string but not being defined as a dimension name. - || dim != null && !isNaN(dim) && !this._getDimInfo(dim) && (!this._dimOmitted || this._schema.getSourceDimensionIndex(dim) < 0)) { - return +dim; - } - }; - - SeriesData.prototype._getStoreDimIndex = function (dim) { - var dimIdx = this.getDimensionIndex(dim); - { - if (dimIdx == null) { - throw new Error('Unknown dimension ' + dim); - } - } - return dimIdx; - }; - /** - * Get type and calculation info of particular dimension - * @param dim - * Dimension can be concrete names like x, y, z, lng, lat, angle, radius - * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius' - */ - - - SeriesData.prototype.getDimensionInfo = function (dim) { - // Do not clone, because there may be categories in dimInfo. - return this._getDimInfo(this.getDimension(dim)); - }; - - SeriesData.prototype._initGetDimensionInfo = function (needsHasOwn) { - var dimensionInfos = this._dimInfos; - this._getDimInfo = needsHasOwn ? function (dimName) { - return dimensionInfos.hasOwnProperty(dimName) ? dimensionInfos[dimName] : undefined; - } : function (dimName) { - return dimensionInfos[dimName]; - }; - }; - /** - * concrete dimension name list on coord. - */ - - - SeriesData.prototype.getDimensionsOnCoord = function () { - return this._dimSummary.dataDimsOnCoord.slice(); - }; - - SeriesData.prototype.mapDimension = function (coordDim, idx) { - var dimensionsSummary = this._dimSummary; - - if (idx == null) { - return dimensionsSummary.encodeFirstDimNotExtra[coordDim]; - } - - var dims = dimensionsSummary.encode[coordDim]; - return dims ? dims[idx] : null; - }; - - SeriesData.prototype.mapDimensionsAll = function (coordDim) { - var dimensionsSummary = this._dimSummary; - var dims = dimensionsSummary.encode[coordDim]; - return (dims || []).slice(); - }; - - SeriesData.prototype.getStore = function () { - return this._store; - }; - /** - * Initialize from data - * @param data source or data or data store. - * @param nameList The name of a datum is used on data diff and - * default label/tooltip. - * A name can be specified in encode.itemName, - * or dataItem.name (only for series option data), - * or provided in nameList from outside. - */ - - - SeriesData.prototype.initData = function (data, nameList, dimValueGetter) { - var _this = this; - - var store; - - if (data instanceof DataStore) { - store = data; - } - - if (!store) { - var dimensions = this.dimensions; - var provider = isSourceInstance(data) || isArrayLike(data) ? new DefaultDataProvider(data, dimensions.length) : data; - store = new DataStore(); - var dimensionInfos = map(dimensions, function (dimName) { - return { - type: _this._dimInfos[dimName].type, - property: dimName - }; - }); - store.initData(provider, dimensionInfos, dimValueGetter); - } - - this._store = store; // Reset - - this._nameList = (nameList || []).slice(); - this._idList = []; - this._nameRepeatCount = {}; - - this._doInit(0, store.count()); // Cache summary info for fast visit. See "dimensionHelper". - // Needs to be initialized after store is prepared. - - - this._dimSummary = summarizeDimensions(this, this._schema); - this.userOutput = this._dimSummary.userOutput; - }; - /** - * Caution: Can be only called on raw data (before `this._indices` created). - */ - - - SeriesData.prototype.appendData = function (data) { - var range = this._store.appendData(data); - - this._doInit(range[0], range[1]); - }; - /** - * Caution: Can be only called on raw data (before `this._indices` created). - * This method does not modify `rawData` (`dataProvider`), but only - * add values to store. - * - * The final count will be increased by `Math.max(values.length, names.length)`. - * - * @param values That is the SourceType: 'arrayRows', like - * [ - * [12, 33, 44], - * [NaN, 43, 1], - * ['-', 'asdf', 0] - * ] - * Each item is exactly corresponding to a dimension. - */ - - - SeriesData.prototype.appendValues = function (values, names) { - var _a = this._store.appendValues(values, names.length), - start = _a.start, - end = _a.end; - - var shouldMakeIdFromName = this._shouldMakeIdFromName(); - - this._updateOrdinalMeta(); - - if (names) { - for (var idx = start; idx < end; idx++) { - var sourceIdx = idx - start; - this._nameList[idx] = names[sourceIdx]; - - if (shouldMakeIdFromName) { - makeIdFromName(this, idx); - } - } - } - }; - - SeriesData.prototype._updateOrdinalMeta = function () { - var store = this._store; - var dimensions = this.dimensions; - - for (var i = 0; i < dimensions.length; i++) { - var dimInfo = this._dimInfos[dimensions[i]]; - - if (dimInfo.ordinalMeta) { - store.collectOrdinalMeta(dimInfo.storeDimIndex, dimInfo.ordinalMeta); - } - } - }; - - SeriesData.prototype._shouldMakeIdFromName = function () { - var provider = this._store.getProvider(); - - return this._idDimIdx == null && provider.getSource().sourceFormat !== SOURCE_FORMAT_TYPED_ARRAY && !provider.fillStorage; - }; - - SeriesData.prototype._doInit = function (start, end) { - if (start >= end) { - return; - } - - var store = this._store; - var provider = store.getProvider(); - - this._updateOrdinalMeta(); - - var nameList = this._nameList; - var idList = this._idList; - var sourceFormat = provider.getSource().sourceFormat; - var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL; // Each data item is value - // [1, 2] - // 2 - // Bar chart, line chart which uses category axis - // only gives the 'y' value. 'x' value is the indices of category - // Use a tempValue to normalize the value to be a (x, y) value - // If dataItem is {name: ...} or {id: ...}, it has highest priority. - // This kind of ids and names are always stored `_nameList` and `_idList`. - - if (isFormatOriginal && !provider.pure) { - var sharedDataItem = []; - - for (var idx = start; idx < end; idx++) { - // NOTICE: Try not to write things into dataItem - var dataItem = provider.getItem(idx, sharedDataItem); - - if (!this.hasItemOption && isDataItemOption(dataItem)) { - this.hasItemOption = true; - } - - if (dataItem) { - var itemName = dataItem.name; - - if (nameList[idx] == null && itemName != null) { - nameList[idx] = convertOptionIdName(itemName, null); - } - - var itemId = dataItem.id; - - if (idList[idx] == null && itemId != null) { - idList[idx] = convertOptionIdName(itemId, null); - } - } - } - } - - if (this._shouldMakeIdFromName()) { - for (var idx = start; idx < end; idx++) { - makeIdFromName(this, idx); - } - } - - prepareInvertedIndex(this); - }; - /** - * PENDING: In fact currently this function is only used to short-circuit - * the calling of `scale.unionExtentFromData` when data have been filtered by modules - * like "dataZoom". `scale.unionExtentFromData` is used to calculate data extent for series on - * an axis, but if a "axis related data filter module" is used, the extent of the axis have - * been fixed and no need to calling `scale.unionExtentFromData` actually. - * But if we add "custom data filter" in future, which is not "axis related", this method may - * be still needed. - * - * Optimize for the scenario that data is filtered by a given extent. - * Consider that if data amount is more than hundreds of thousand, - * extent calculation will cost more than 10ms and the cache will - * be erased because of the filtering. - */ - - - SeriesData.prototype.getApproximateExtent = function (dim) { - return this._approximateExtent[dim] || this._store.getDataExtent(this._getStoreDimIndex(dim)); - }; - /** - * Calculate extent on a filtered data might be time consuming. - * Approximate extent is only used for: calculate extent of filtered data outside. - */ - - - SeriesData.prototype.setApproximateExtent = function (extent, dim) { - dim = this.getDimension(dim); - this._approximateExtent[dim] = extent.slice(); - }; - - SeriesData.prototype.getCalculationInfo = function (key) { - return this._calculationInfo[key]; - }; - - SeriesData.prototype.setCalculationInfo = function (key, value) { - isObject(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value; - }; - /** - * @return Never be null/undefined. `number` will be converted to string. Because: - * In most cases, name is used in display, where returning a string is more convenient. - * In other cases, name is used in query (see `indexOfName`), where we can keep the - * rule that name `2` equals to name `'2'`. - */ - - - SeriesData.prototype.getName = function (idx) { - var rawIndex = this.getRawIndex(idx); - var name = this._nameList[rawIndex]; - - if (name == null && this._nameDimIdx != null) { - name = getIdNameFromStore(this, this._nameDimIdx, rawIndex); - } - - if (name == null) { - name = ''; - } - - return name; - }; - - SeriesData.prototype._getCategory = function (dimIdx, idx) { - var ordinal = this._store.get(dimIdx, idx); - - var ordinalMeta = this._store.getOrdinalMeta(dimIdx); - - if (ordinalMeta) { - return ordinalMeta.categories[ordinal]; - } - - return ordinal; - }; - /** - * @return Never null/undefined. `number` will be converted to string. Because: - * In all cases having encountered at present, id is used in making diff comparison, which - * are usually based on hash map. We can keep the rule that the internal id are always string - * (treat `2` is the same as `'2'`) to make the related logic simple. - */ - - - SeriesData.prototype.getId = function (idx) { - return getId(this, this.getRawIndex(idx)); - }; - - SeriesData.prototype.count = function () { - return this._store.count(); - }; - /** - * Get value. Return NaN if idx is out of range. - * - * @notice Should better to use `data.getStore().get(dimIndex, dataIdx)` instead. - */ - - - SeriesData.prototype.get = function (dim, idx) { - var store = this._store; - var dimInfo = this._dimInfos[dim]; - - if (dimInfo) { - return store.get(dimInfo.storeDimIndex, idx); - } - }; - /** - * @notice Should better to use `data.getStore().getByRawIndex(dimIndex, dataIdx)` instead. - */ - - - SeriesData.prototype.getByRawIndex = function (dim, rawIdx) { - var store = this._store; - var dimInfo = this._dimInfos[dim]; - - if (dimInfo) { - return store.getByRawIndex(dimInfo.storeDimIndex, rawIdx); - } - }; - - SeriesData.prototype.getIndices = function () { - return this._store.getIndices(); - }; - - SeriesData.prototype.getDataExtent = function (dim) { - return this._store.getDataExtent(this._getStoreDimIndex(dim)); - }; - - SeriesData.prototype.getSum = function (dim) { - return this._store.getSum(this._getStoreDimIndex(dim)); - }; - - SeriesData.prototype.getMedian = function (dim) { - return this._store.getMedian(this._getStoreDimIndex(dim)); - }; - - SeriesData.prototype.getValues = function (dimensions, idx) { - var _this = this; - - var store = this._store; - return isArray(dimensions) ? store.getValues(map(dimensions, function (dim) { - return _this._getStoreDimIndex(dim); - }), idx) : store.getValues(dimensions); - }; - /** - * If value is NaN. Including '-' - * Only check the coord dimensions. - */ - - - SeriesData.prototype.hasValue = function (idx) { - var dataDimIndicesOnCoord = this._dimSummary.dataDimIndicesOnCoord; - - for (var i = 0, len = dataDimIndicesOnCoord.length; i < len; i++) { - // Ordinal type originally can be string or number. - // But when an ordinal type is used on coord, it can - // not be string but only number. So we can also use isNaN. - if (isNaN(this._store.get(dataDimIndicesOnCoord[i], idx))) { - return false; - } - } - - return true; - }; - /** - * Retrieve the index with given name - */ - - - SeriesData.prototype.indexOfName = function (name) { - for (var i = 0, len = this._store.count(); i < len; i++) { - if (this.getName(i) === name) { - return i; - } - } - - return -1; - }; - - SeriesData.prototype.getRawIndex = function (idx) { - return this._store.getRawIndex(idx); - }; - - SeriesData.prototype.indexOfRawIndex = function (rawIndex) { - return this._store.indexOfRawIndex(rawIndex); - }; - /** - * Only support the dimension which inverted index created. - * Do not support other cases until required. - * @param dim concrete dim - * @param value ordinal index - * @return rawIndex - */ - - - SeriesData.prototype.rawIndexOf = function (dim, value) { - var invertedIndices = dim && this._invertedIndicesMap[dim]; - { - if (!invertedIndices) { - throw new Error('Do not supported yet'); - } - } - var rawIndex = invertedIndices[value]; - - if (rawIndex == null || isNaN(rawIndex)) { - return INDEX_NOT_FOUND; - } - - return rawIndex; - }; - /** - * Retrieve the index of nearest value - * @param dim - * @param value - * @param [maxDistance=Infinity] - * @return If and only if multiple indices has - * the same value, they are put to the result. - */ - - - SeriesData.prototype.indicesOfNearest = function (dim, value, maxDistance) { - return this._store.indicesOfNearest(this._getStoreDimIndex(dim), value, maxDistance); - }; - - SeriesData.prototype.each = function (dims, cb, ctx) { - if (isFunction(dims)) { - ctx = cb; - cb = dims; - dims = []; - } // ctxCompat just for compat echarts3 - - - var fCtx = ctx || this; - var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); - - this._store.each(dimIndices, fCtx ? bind$1(cb, fCtx) : cb); - }; - - SeriesData.prototype.filterSelf = function (dims, cb, ctx) { - if (isFunction(dims)) { - ctx = cb; - cb = dims; - dims = []; - } // ctxCompat just for compat echarts3 - - - var fCtx = ctx || this; - var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); - this._store = this._store.filter(dimIndices, fCtx ? bind$1(cb, fCtx) : cb); - return this; - }; - /** - * Select data in range. (For optimization of filter) - * (Manually inline code, support 5 million data filtering in data zoom.) - */ - - - SeriesData.prototype.selectRange = function (range) { - var _this = this; - - var innerRange = {}; - var dims = keys(range); - each$4(dims, function (dim) { - var dimIdx = _this._getStoreDimIndex(dim); - - innerRange[dimIdx] = range[dim]; - }); - this._store = this._store.selectRange(innerRange); - return this; - }; - /* eslint-enable max-len */ - - - SeriesData.prototype.mapArray = function (dims, cb, ctx) { - if (isFunction(dims)) { - ctx = cb; - cb = dims; - dims = []; - } // ctxCompat just for compat echarts3 - - - ctx = ctx || this; - var result = []; - this.each(dims, function () { - result.push(cb && cb.apply(this, arguments)); - }, ctx); - return result; - }; - - SeriesData.prototype.map = function (dims, cb, ctx, ctxCompat) { - // ctxCompat just for compat echarts3 - var fCtx = ctx || ctxCompat || this; - var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); - var list = cloneListForMapAndSample(this); - list._store = this._store.map(dimIndices, fCtx ? bind$1(cb, fCtx) : cb); - return list; - }; - - SeriesData.prototype.modify = function (dims, cb, ctx, ctxCompat) { - var _this = this; // ctxCompat just for compat echarts3 - - - var fCtx = ctx || ctxCompat || this; - { - each$4(normalizeDimensions(dims), function (dim) { - var dimInfo = _this.getDimensionInfo(dim); - - if (!dimInfo.isCalculationCoord) { - console.error('Danger: only stack dimension can be modified'); - } - }); - } - var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); // If do shallow clone here, if there are too many stacked series, - // it still cost lots of memory, because `_store.dimensions` are not shared. - // We should consider there probably be shallow clone happen in each series - // in consequent filter/map. - - this._store.modify(dimIndices, fCtx ? bind$1(cb, fCtx) : cb); - }; - /** - * Large data down sampling on given dimension - * @param sampleIndex Sample index for name and id - */ - - - SeriesData.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) { - var list = cloneListForMapAndSample(this); - list._store = this._store.downSample(this._getStoreDimIndex(dimension), rate, sampleValue, sampleIndex); - return list; - }; - /** - * Large data down sampling using largest-triangle-three-buckets - * @param {string} valueDimension - * @param {number} targetCount - */ - - - SeriesData.prototype.lttbDownSample = function (valueDimension, rate) { - var list = cloneListForMapAndSample(this); - list._store = this._store.lttbDownSample(this._getStoreDimIndex(valueDimension), rate); - return list; - }; - - SeriesData.prototype.getRawDataItem = function (idx) { - return this._store.getRawDataItem(idx); - }; - /** - * Get model of one data item. - */ - // TODO: Type of data item - - - SeriesData.prototype.getItemModel = function (idx) { - var hostModel = this.hostModel; - var dataItem = this.getRawDataItem(idx); - return new Model(dataItem, hostModel, hostModel && hostModel.ecModel); - }; - /** - * Create a data differ - */ - - - SeriesData.prototype.diff = function (otherList) { - var thisList = this; - return new DataDiffer(otherList ? otherList.getStore().getIndices() : [], this.getStore().getIndices(), function (idx) { - return getId(otherList, idx); - }, function (idx) { - return getId(thisList, idx); - }); - }; - /** - * Get visual property. - */ - - - SeriesData.prototype.getVisual = function (key) { - var visual = this._visual; - return visual && visual[key]; - }; - - SeriesData.prototype.setVisual = function (kvObj, val) { - this._visual = this._visual || {}; - - if (isObject(kvObj)) { - extend(this._visual, kvObj); - } else { - this._visual[kvObj] = val; - } - }; - /** - * Get visual property of single data item - */ - // eslint-disable-next-line - - - SeriesData.prototype.getItemVisual = function (idx, key) { - var itemVisual = this._itemVisuals[idx]; - var val = itemVisual && itemVisual[key]; - - if (val == null) { - // Use global visual property - return this.getVisual(key); - } - - return val; - }; - /** - * If exists visual property of single data item - */ - - - SeriesData.prototype.hasItemVisual = function () { - return this._itemVisuals.length > 0; - }; - /** - * Make sure itemVisual property is unique - */ - // TODO: use key to save visual to reduce memory. - - - SeriesData.prototype.ensureUniqueItemVisual = function (idx, key) { - var itemVisuals = this._itemVisuals; - var itemVisual = itemVisuals[idx]; - - if (!itemVisual) { - itemVisual = itemVisuals[idx] = {}; - } - - var val = itemVisual[key]; - - if (val == null) { - val = this.getVisual(key); // TODO Performance? - - if (isArray(val)) { - val = val.slice(); - } else if (isObject(val)) { - val = extend({}, val); - } - - itemVisual[key] = val; - } - - return val; - }; // eslint-disable-next-line - - - SeriesData.prototype.setItemVisual = function (idx, key, value) { - var itemVisual = this._itemVisuals[idx] || {}; - this._itemVisuals[idx] = itemVisual; - - if (isObject(key)) { - extend(itemVisual, key); - } else { - itemVisual[key] = value; - } - }; - /** - * Clear itemVisuals and list visual. - */ - - - SeriesData.prototype.clearAllVisual = function () { - this._visual = {}; - this._itemVisuals = []; - }; - - SeriesData.prototype.setLayout = function (key, val) { - isObject(key) ? extend(this._layout, key) : this._layout[key] = val; - }; - /** - * Get layout property. - */ - - - SeriesData.prototype.getLayout = function (key) { - return this._layout[key]; - }; - /** - * Get layout of single data item - */ - - - SeriesData.prototype.getItemLayout = function (idx) { - return this._itemLayouts[idx]; - }; - /** - * Set layout of single data item - */ - - - SeriesData.prototype.setItemLayout = function (idx, layout, merge) { - this._itemLayouts[idx] = merge ? extend(this._itemLayouts[idx] || {}, layout) : layout; - }; - /** - * Clear all layout of single data item - */ - - - SeriesData.prototype.clearItemLayouts = function () { - this._itemLayouts.length = 0; - }; - /** - * Set graphic element relative to data. It can be set as null - */ - - - SeriesData.prototype.setItemGraphicEl = function (idx, el) { - var seriesIndex = this.hostModel && this.hostModel.seriesIndex; - setCommonECData(seriesIndex, this.dataType, idx, el); - this._graphicEls[idx] = el; - }; - - SeriesData.prototype.getItemGraphicEl = function (idx) { - return this._graphicEls[idx]; - }; - - SeriesData.prototype.eachItemGraphicEl = function (cb, context) { - each$4(this._graphicEls, function (el, idx) { - if (el) { - cb && cb.call(context, el, idx); - } - }); - }; - /** - * Shallow clone a new list except visual and layout properties, and graph elements. - * New list only change the indices. - */ - - - SeriesData.prototype.cloneShallow = function (list) { - if (!list) { - list = new SeriesData(this._schema ? this._schema : map(this.dimensions, this._getDimInfo, this), this.hostModel); - } - - transferProperties(list, this); - list._store = this._store; - return list; - }; - /** - * Wrap some method to add more feature - */ - - - SeriesData.prototype.wrapMethod = function (methodName, injectFunction) { - var originalMethod = this[methodName]; - - if (!isFunction(originalMethod)) { - return; - } - - this.__wrappedMethods = this.__wrappedMethods || []; - - this.__wrappedMethods.push(methodName); - - this[methodName] = function () { - var res = originalMethod.apply(this, arguments); - return injectFunction.apply(this, [res].concat(slice(arguments))); - }; - }; // ---------------------------------------------------------- - // A work around for internal method visiting private member. - // ---------------------------------------------------------- - - - SeriesData.internalField = function () { - prepareInvertedIndex = function (data) { - var invertedIndicesMap = data._invertedIndicesMap; - each$4(invertedIndicesMap, function (invertedIndices, dim) { - var dimInfo = data._dimInfos[dim]; // Currently, only dimensions that has ordinalMeta can create inverted indices. - - var ordinalMeta = dimInfo.ordinalMeta; - var store = data._store; - - if (ordinalMeta) { - invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); // The default value of TypedArray is 0. To avoid miss - // mapping to 0, we should set it as INDEX_NOT_FOUND. - - for (var i = 0; i < invertedIndices.length; i++) { - invertedIndices[i] = INDEX_NOT_FOUND; - } - - for (var i = 0; i < store.count(); i++) { - // Only support the case that all values are distinct. - invertedIndices[store.get(dimInfo.storeDimIndex, i)] = i; - } - } - }); - }; - - getIdNameFromStore = function (data, dimIdx, idx) { - return convertOptionIdName(data._getCategory(dimIdx, idx), null); - }; - /** - * @see the comment of `List['getId']`. - */ - - - getId = function (data, rawIndex) { - var id = data._idList[rawIndex]; - - if (id == null && data._idDimIdx != null) { - id = getIdNameFromStore(data, data._idDimIdx, rawIndex); - } - - if (id == null) { - id = ID_PREFIX + rawIndex; - } - - return id; - }; - - normalizeDimensions = function (dimensions) { - if (!isArray(dimensions)) { - dimensions = dimensions != null ? [dimensions] : []; - } - - return dimensions; - }; - /** - * Data in excludeDimensions is copied, otherwise transferred. - */ - - - cloneListForMapAndSample = function (original) { - var list = new SeriesData(original._schema ? original._schema : map(original.dimensions, original._getDimInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked - - transferProperties(list, original); - return list; - }; - - transferProperties = function (target, source) { - each$4(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) { - if (source.hasOwnProperty(propName)) { - target[propName] = source[propName]; - } - }); - target.__wrappedMethods = source.__wrappedMethods; - each$4(CLONE_PROPERTIES, function (propName) { - target[propName] = clone$3(source[propName]); - }); - target._calculationInfo = extend({}, source._calculationInfo); - }; - - makeIdFromName = function (data, idx) { - var nameList = data._nameList; - var idList = data._idList; - var nameDimIdx = data._nameDimIdx; - var idDimIdx = data._idDimIdx; - var name = nameList[idx]; - var id = idList[idx]; - - if (name == null && nameDimIdx != null) { - nameList[idx] = name = getIdNameFromStore(data, nameDimIdx, idx); - } - - if (id == null && idDimIdx != null) { - idList[idx] = id = getIdNameFromStore(data, idDimIdx, idx); - } - - if (id == null && name != null) { - var nameRepeatCount = data._nameRepeatCount; - var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1; - id = name; - - if (nmCnt > 1) { - id += '__ec__' + nmCnt; - } - - idList[idx] = id; - } - }; - }(); - - return SeriesData; - }(); - /** - * For outside usage compat (like echarts-gl are using it). - */ - - - function createDimensions(source, opt) { - return prepareSeriesDataSchema(source, opt).dimensions; - } - /** - * This method builds the relationship between: - * + "what the coord sys or series requires (see `coordDimensions`)", - * + "what the user defines (in `encode` and `dimensions`, see `opt.dimensionsDefine` and `opt.encodeDefine`)" - * + "what the data source provids (see `source`)". - * - * Some guess strategy will be adapted if user does not define something. - * If no 'value' dimension specified, the first no-named dimension will be - * named as 'value'. - * - * @return The results are always sorted by `storeDimIndex` asc. - */ - - - function prepareSeriesDataSchema( // TODO: TYPE completeDimensions type - source, opt) { - if (!isSourceInstance(source)) { - source = createSourceFromSeriesDataOption(source); - } - - opt = opt || {}; - var sysDims = opt.coordDimensions || []; - var dimsDef = opt.dimensionsDefine || source.dimensionsDefine || []; - var coordDimNameMap = createHashMap(); - var resultList = []; - var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimensionsCount); // Try to ignore unused dimensions if sharing a high dimension datastore - // 30 is an experience value. - - var omitUnusedDimensions = opt.canOmitUnusedDimensions && shouldOmitUnusedDimensions(dimCount); - var isUsingSourceDimensionsDef = dimsDef === source.dimensionsDefine; - var dataDimNameMap = isUsingSourceDimensionsDef ? ensureSourceDimNameMap(source) : createDimNameMap(dimsDef); - var encodeDef = opt.encodeDefine; - - if (!encodeDef && opt.encodeDefaulter) { - encodeDef = opt.encodeDefaulter(source, dimCount); - } - - var encodeDefMap = createHashMap(encodeDef); - var indicesMap = new CtorInt32Array$1(dimCount); - - for (var i = 0; i < indicesMap.length; i++) { - indicesMap[i] = -1; - } - - function getResultItem(dimIdx) { - var idx = indicesMap[dimIdx]; - - if (idx < 0) { - var dimDefItemRaw = dimsDef[dimIdx]; - var dimDefItem = isObject$2(dimDefItemRaw) ? dimDefItemRaw : { - name: dimDefItemRaw - }; - var resultItem = new SeriesDimensionDefine(); - var userDimName = dimDefItem.name; - - if (userDimName != null && dataDimNameMap.get(userDimName) != null) { - // Only if `series.dimensions` is defined in option - // displayName, will be set, and dimension will be displayed vertically in - // tooltip by default. - resultItem.name = resultItem.displayName = userDimName; - } - - dimDefItem.type != null && (resultItem.type = dimDefItem.type); - dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); - var newIdx = resultList.length; - indicesMap[dimIdx] = newIdx; - resultItem.storeDimIndex = dimIdx; - resultList.push(resultItem); - return resultItem; - } - - return resultList[idx]; - } - - if (!omitUnusedDimensions) { - for (var i = 0; i < dimCount; i++) { - getResultItem(i); - } - } // Set `coordDim` and `coordDimIndex` by `encodeDefMap` and normalize `encodeDefMap`. - - - encodeDefMap.each(function (dataDimsRaw, coordDim) { - var dataDims = normalizeToArray(dataDimsRaw).slice(); // Note: It is allowed that `dataDims.length` is `0`, e.g., options is - // `{encode: {x: -1, y: 1}}`. Should not filter anything in - // this case. - - if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) { - encodeDefMap.set(coordDim, false); - return; - } - - var validDataDims = encodeDefMap.set(coordDim, []); - each$4(dataDims, function (resultDimIdxOrName, idx) { - // The input resultDimIdx can be dim name or index. - var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName; - - if (resultDimIdx != null && resultDimIdx < dimCount) { - validDataDims[idx] = resultDimIdx; - applyDim(getResultItem(resultDimIdx), coordDim, idx); - } - }); - }); // Apply templates and default order from `sysDims`. - - var availDimIdx = 0; - each$4(sysDims, function (sysDimItemRaw) { - var coordDim; - var sysDimItemDimsDef; - var sysDimItemOtherDims; - var sysDimItem; - - if (isString(sysDimItemRaw)) { - coordDim = sysDimItemRaw; - sysDimItem = {}; - } else { - sysDimItem = sysDimItemRaw; - coordDim = sysDimItem.name; - var ordinalMeta = sysDimItem.ordinalMeta; - sysDimItem.ordinalMeta = null; - sysDimItem = extend({}, sysDimItem); - sysDimItem.ordinalMeta = ordinalMeta; // `coordDimIndex` should not be set directly. - - sysDimItemDimsDef = sysDimItem.dimsDef; - sysDimItemOtherDims = sysDimItem.otherDims; - sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null; - } - - var dataDims = encodeDefMap.get(coordDim); // negative resultDimIdx means no need to mapping. - - if (dataDims === false) { - return; - } - - dataDims = normalizeToArray(dataDims); // dimensions provides default dim sequences. - - if (!dataDims.length) { - for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { - while (availDimIdx < dimCount && getResultItem(availDimIdx).coordDim != null) { - availDimIdx++; - } - - availDimIdx < dimCount && dataDims.push(availDimIdx++); - } - } // Apply templates. - - - each$4(dataDims, function (resultDimIdx, coordDimIndex) { - var resultItem = getResultItem(resultDimIdx); // Coordinate system has a higher priority on dim type than source. - - if (isUsingSourceDimensionsDef && sysDimItem.type != null) { - resultItem.type = sysDimItem.type; - } - - applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); - - if (resultItem.name == null && sysDimItemDimsDef) { - var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex]; - !isObject$2(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = { - name: sysDimItemDimsDefItem - }); - resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name; - resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip; - } // FIXME refactor, currently only used in case: {otherDims: {tooltip: false}} - - - sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); - }); - }); - - function applyDim(resultItem, coordDim, coordDimIndex) { - if (VISUAL_DIMENSIONS.get(coordDim) != null) { - resultItem.otherDims[coordDim] = coordDimIndex; - } else { - resultItem.coordDim = coordDim; - resultItem.coordDimIndex = coordDimIndex; - coordDimNameMap.set(coordDim, true); - } - } // Make sure the first extra dim is 'value'. - - - var generateCoord = opt.generateCoord; - var generateCoordCount = opt.generateCoordCount; - var fromZero = generateCoordCount != null; - generateCoordCount = generateCoord ? generateCoordCount || 1 : 0; - var extra = generateCoord || 'value'; - - function ifNoNameFillWithCoordName(resultItem) { - if (resultItem.name == null) { - // Duplication will be removed in the next step. - resultItem.name = resultItem.coordDim; - } - } // Set dim `name` and other `coordDim` and other props. - - - if (!omitUnusedDimensions) { - for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { - var resultItem = getResultItem(resultDimIdx); - var coordDim = resultItem.coordDim; - - if (coordDim == null) { - // TODO no need to generate coordDim for isExtraCoord? - resultItem.coordDim = genCoordDimName(extra, coordDimNameMap, fromZero); - resultItem.coordDimIndex = 0; // Series specified generateCoord is using out. - - if (!generateCoord || generateCoordCount <= 0) { - resultItem.isExtraCoord = true; - } - - generateCoordCount--; - } - - ifNoNameFillWithCoordName(resultItem); - - if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must // Consider the case: - // { - // dataset: {source: [ - // ['2001', 123], - // ['2002', 456], - // ... - // ['The others', 987], - // ]}, - // series: {type: 'pie'} - // } - // The first column should better be treated as a "ordinal" although it - // might not be detected as an "ordinal" by `guessOrdinal`. - || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) { - resultItem.type = 'ordinal'; - } - } - } else { - each$4(resultList, function (resultItem) { - // PENDING: guessOrdinal or let user specify type: 'ordinal' manually? - ifNoNameFillWithCoordName(resultItem); - }); // Sort dimensions: there are some rule that use the last dim as label, - // and for some latter travel process easier. - - resultList.sort(function (item0, item1) { - return item0.storeDimIndex - item1.storeDimIndex; - }); - } - - removeDuplication(resultList); - return new SeriesDataSchema({ - source: source, - dimensions: resultList, - fullDimensionCount: dimCount, - dimensionOmitted: omitUnusedDimensions - }); - } - - function removeDuplication(result) { - var duplicationMap = createHashMap(); - - for (var i = 0; i < result.length; i++) { - var dim = result[i]; - var dimOriginalName = dim.name; - var count = duplicationMap.get(dimOriginalName) || 0; - - if (count > 0) { - // Starts from 0. - dim.name = dimOriginalName + (count - 1); - } - - count++; - duplicationMap.set(dimOriginalName, count); - } - } // ??? TODO - // Originally detect dimCount by data[0]. Should we - // optimize it to only by sysDims and dimensions and encode. - // So only necessary dims will be initialized. - // But - // (1) custom series should be considered. where other dims - // may be visited. - // (2) sometimes user need to calculate bubble size or use visualMap - // on other dimensions besides coordSys needed. - // So, dims that is not used by system, should be shared in data store? - - - function getDimCount(source, sysDims, dimsDef, optDimCount) { - // Note that the result dimCount should not small than columns count - // of data, otherwise `dataDimNameMap` checking will be incorrect. - var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0); - each$4(sysDims, function (sysDimItem) { - var sysDimItemDimsDef; - - if (isObject$2(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) { - dimCount = Math.max(dimCount, sysDimItemDimsDef.length); - } - }); - return dimCount; - } - - function genCoordDimName(name, map, fromZero) { - if (fromZero || map.hasKey(name)) { - var i = 0; - - while (map.hasKey(name + i)) { - i++; - } - - name += i; - } - - map.set(name, true); - return name; - } - /** - * @class - * For example: - * { - * coordSysName: 'cartesian2d', - * coordSysDims: ['x', 'y', ...], - * axisMap: HashMap({ - * x: xAxisModel, - * y: yAxisModel - * }), - * categoryAxisMap: HashMap({ - * x: xAxisModel, - * y: undefined - * }), - * // The index of the first category axis in `coordSysDims`. - * // `null/undefined` means no category axis exists. - * firstCategoryDimIndex: 1, - * // To replace user specified encode. - * } - */ - - - var CoordSysInfo = - /** @class */ - function () { - function CoordSysInfo(coordSysName) { - this.coordSysDims = []; - this.axisMap = createHashMap(); - this.categoryAxisMap = createHashMap(); - this.coordSysName = coordSysName; - } - - return CoordSysInfo; - }(); - - function getCoordSysInfoBySeries(seriesModel) { - var coordSysName = seriesModel.get('coordinateSystem'); - var result = new CoordSysInfo(coordSysName); - var fetch = fetchers[coordSysName]; - - if (fetch) { - fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); - return result; - } - } - - var fetchers = { - cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) { - var xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; - var yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; - { - if (!xAxisModel) { - throw new Error('xAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('xAxisId'), 0) + '" not found'); - } - - if (!yAxisModel) { - throw new Error('yAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('yAxisId'), 0) + '" not found'); - } - } - result.coordSysDims = ['x', 'y']; - axisMap.set('x', xAxisModel); - axisMap.set('y', yAxisModel); - - if (isCategory(xAxisModel)) { - categoryAxisMap.set('x', xAxisModel); - result.firstCategoryDimIndex = 0; - } - - if (isCategory(yAxisModel)) { - categoryAxisMap.set('y', yAxisModel); - result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); - } - }, - singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) { - var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; - { - if (!singleAxisModel) { - throw new Error('singleAxis should be specified.'); - } - } - result.coordSysDims = ['single']; - axisMap.set('single', singleAxisModel); - - if (isCategory(singleAxisModel)) { - categoryAxisMap.set('single', singleAxisModel); - result.firstCategoryDimIndex = 0; - } - }, - polar: function (seriesModel, result, axisMap, categoryAxisMap) { - var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0]; - var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); - var angleAxisModel = polarModel.findAxisModel('angleAxis'); - { - if (!angleAxisModel) { - throw new Error('angleAxis option not found'); - } - - if (!radiusAxisModel) { - throw new Error('radiusAxis option not found'); - } - } - result.coordSysDims = ['radius', 'angle']; - axisMap.set('radius', radiusAxisModel); - axisMap.set('angle', angleAxisModel); - - if (isCategory(radiusAxisModel)) { - categoryAxisMap.set('radius', radiusAxisModel); - result.firstCategoryDimIndex = 0; - } - - if (isCategory(angleAxisModel)) { - categoryAxisMap.set('angle', angleAxisModel); - result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); - } - }, - geo: function (seriesModel, result, axisMap, categoryAxisMap) { - result.coordSysDims = ['lng', 'lat']; - }, - parallel: function (seriesModel, result, axisMap, categoryAxisMap) { - var ecModel = seriesModel.ecModel; - var parallelModel = ecModel.getComponent('parallel', seriesModel.get('parallelIndex')); - var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); - each$4(parallelModel.parallelAxisIndex, function (axisIndex, index) { - var axisModel = ecModel.getComponent('parallelAxis', axisIndex); - var axisDim = coordSysDims[index]; - axisMap.set(axisDim, axisModel); - - if (isCategory(axisModel)) { - categoryAxisMap.set(axisDim, axisModel); - - if (result.firstCategoryDimIndex == null) { - result.firstCategoryDimIndex = index; - } - } - }); - } - }; - - function isCategory(axisModel) { - return axisModel.get('type') === 'category'; - } - /** - * Note that it is too complicated to support 3d stack by value - * (have to create two-dimension inverted index), so in 3d case - * we just support that stacked by index. - * - * @param seriesModel - * @param dimensionsInput The same as the input of . - * The input will be modified. - * @param opt - * @param opt.stackedCoordDimension Specify a coord dimension if needed. - * @param opt.byIndex=false - * @return calculationInfo - * { - * stackedDimension: string - * stackedByDimension: string - * isStackedByIndex: boolean - * stackedOverDimension: string - * stackResultDimension: string - * } - */ - - - function enableDataStack(seriesModel, dimensionsInput, opt) { - opt = opt || {}; - var byIndex = opt.byIndex; - var stackedCoordDimension = opt.stackedCoordDimension; - var dimensionDefineList; - var schema; - var store; - - if (isLegacyDimensionsInput(dimensionsInput)) { - dimensionDefineList = dimensionsInput; - } else { - schema = dimensionsInput.schema; - dimensionDefineList = schema.dimensions; - store = dimensionsInput.store; - } // Compatibal: when `stack` is set as '', do not stack. - - - var mayStack = !!(seriesModel && seriesModel.get('stack')); - var stackedByDimInfo; - var stackedDimInfo; - var stackResultDimension; - var stackedOverDimension; - each$4(dimensionDefineList, function (dimensionInfo, index) { - if (isString(dimensionInfo)) { - dimensionDefineList[index] = dimensionInfo = { - name: dimensionInfo - }; - } - - if (mayStack && !dimensionInfo.isExtraCoord) { - // Find the first ordinal dimension as the stackedByDimInfo. - if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { - stackedByDimInfo = dimensionInfo; - } // Find the first stackable dimension as the stackedDimInfo. - - - if (!stackedDimInfo && dimensionInfo.type !== 'ordinal' && dimensionInfo.type !== 'time' && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)) { - stackedDimInfo = dimensionInfo; - } - } - }); - - if (stackedDimInfo && !byIndex && !stackedByDimInfo) { - // Compatible with previous design, value axis (time axis) only stack by index. - // It may make sense if the user provides elaborately constructed data. - byIndex = true; - } // Add stack dimension, they can be both calculated by coordinate system in `unionExtent`. - // That put stack logic in List is for using conveniently in echarts extensions, but it - // might not be a good way. - - - if (stackedDimInfo) { - // Use a weird name that not duplicated with other names. - // Also need to use seriesModel.id as postfix because different - // series may share same data store. The stack dimension needs to be distinguished. - stackResultDimension = '__\0ecstackresult_' + seriesModel.id; - stackedOverDimension = '__\0ecstackedover_' + seriesModel.id; // Create inverted index to fast query index by value. - - if (stackedByDimInfo) { - stackedByDimInfo.createInvertedIndices = true; - } - - var stackedDimCoordDim_1 = stackedDimInfo.coordDim; - var stackedDimType = stackedDimInfo.type; - var stackedDimCoordIndex_1 = 0; - each$4(dimensionDefineList, function (dimensionInfo) { - if (dimensionInfo.coordDim === stackedDimCoordDim_1) { - stackedDimCoordIndex_1++; - } - }); - var stackedOverDimensionDefine = { - name: stackResultDimension, - coordDim: stackedDimCoordDim_1, - coordDimIndex: stackedDimCoordIndex_1, - type: stackedDimType, - isExtraCoord: true, - isCalculationCoord: true, - storeDimIndex: dimensionDefineList.length - }; - var stackResultDimensionDefine = { - name: stackedOverDimension, - // This dimension contains stack base (generally, 0), so do not set it as - // `stackedDimCoordDim` to avoid extent calculation, consider log scale. - coordDim: stackedOverDimension, - coordDimIndex: stackedDimCoordIndex_1 + 1, - type: stackedDimType, - isExtraCoord: true, - isCalculationCoord: true, - storeDimIndex: dimensionDefineList.length + 1 - }; - - if (schema) { - if (store) { - stackedOverDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackedOverDimension, stackedDimType); - stackResultDimensionDefine.storeDimIndex = store.ensureCalculationDimension(stackResultDimension, stackedDimType); - } - - schema.appendCalculationDimension(stackedOverDimensionDefine); - schema.appendCalculationDimension(stackResultDimensionDefine); - } else { - dimensionDefineList.push(stackedOverDimensionDefine); - dimensionDefineList.push(stackResultDimensionDefine); - } - } - - return { - stackedDimension: stackedDimInfo && stackedDimInfo.name, - stackedByDimension: stackedByDimInfo && stackedByDimInfo.name, - isStackedByIndex: byIndex, - stackedOverDimension: stackedOverDimension, - stackResultDimension: stackResultDimension - }; - } - - function isLegacyDimensionsInput(dimensionsInput) { - return !isSeriesDataSchema(dimensionsInput.schema); - } - - function isDimensionStacked(data, stackedDim) { - // Each single series only maps to one pair of axis. So we do not need to - // check stackByDim, whatever stacked by a dimension or stacked by index. - return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension'); - } - - function getStackedDimension(data, targetDim) { - return isDimensionStacked(data, targetDim) ? data.getCalculationInfo('stackResultDimension') : targetDim; - } - - function getCoordSysDimDefs(seriesModel, coordSysInfo) { - var coordSysName = seriesModel.get('coordinateSystem'); - var registeredCoordSys = CoordinateSystemManager.get(coordSysName); - var coordSysDimDefs; - - if (coordSysInfo && coordSysInfo.coordSysDims) { - coordSysDimDefs = map$1(coordSysInfo.coordSysDims, function (dim) { - var dimInfo = { - name: dim - }; - var axisModel = coordSysInfo.axisMap.get(dim); - - if (axisModel) { - var axisType = axisModel.get('type'); - dimInfo.type = getDimensionTypeByAxis(axisType); - } - - return dimInfo; - }); - } - - if (!coordSysDimDefs) { - // Get dimensions from registered coordinate system - coordSysDimDefs = registeredCoordSys && (registeredCoordSys.getDimensionsInfo ? registeredCoordSys.getDimensionsInfo() : registeredCoordSys.dimensions.slice()) || ['x', 'y']; - } - - return coordSysDimDefs; - } - - function injectOrdinalMeta(dimInfoList, createInvertedIndices, coordSysInfo) { - var firstCategoryDimIndex; - var hasNameEncode; - coordSysInfo && each$4(dimInfoList, function (dimInfo, dimIndex) { - var coordDim = dimInfo.coordDim; - var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim); - - if (categoryAxisModel) { - if (firstCategoryDimIndex == null) { - firstCategoryDimIndex = dimIndex; - } - - dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta(); - - if (createInvertedIndices) { - dimInfo.createInvertedIndices = true; - } - } - - if (dimInfo.otherDims.itemName != null) { - hasNameEncode = true; - } - }); - - if (!hasNameEncode && firstCategoryDimIndex != null) { - dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0; - } - - return firstCategoryDimIndex; - } - /** - * Caution: there are side effects to `sourceManager` in this method. - * Should better only be called in `Series['getInitialData']`. - */ - - - function createSeriesData(sourceRaw, seriesModel, opt) { - opt = opt || {}; - var sourceManager = seriesModel.getSourceManager(); - var source; - var isOriginalSource = false; - - if (sourceRaw) { - isOriginalSource = true; - source = createSourceFromSeriesDataOption(sourceRaw); - } else { - source = sourceManager.getSource(); // Is series.data. not dataset. - - isOriginalSource = source.sourceFormat === SOURCE_FORMAT_ORIGINAL; - } - - var coordSysInfo = getCoordSysInfoBySeries(seriesModel); - var coordSysDimDefs = getCoordSysDimDefs(seriesModel, coordSysInfo); - var useEncodeDefaulter = opt.useEncodeDefaulter; - var encodeDefaulter = isFunction(useEncodeDefaulter) ? useEncodeDefaulter : useEncodeDefaulter ? curry$1(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null; - var createDimensionOptions = { - coordDimensions: coordSysDimDefs, - generateCoord: opt.generateCoord, - encodeDefine: seriesModel.getEncode(), - encodeDefaulter: encodeDefaulter, - canOmitUnusedDimensions: !isOriginalSource - }; - var schema = prepareSeriesDataSchema(source, createDimensionOptions); - var firstCategoryDimIndex = injectOrdinalMeta(schema.dimensions, opt.createInvertedIndices, coordSysInfo); - var store = !isOriginalSource ? sourceManager.getSharedDataStore(schema) : null; - var stackCalculationInfo = enableDataStack(seriesModel, { - schema: schema, - store: store - }); - var data = new SeriesData(schema, seriesModel); - data.setCalculationInfo(stackCalculationInfo); - var dimValueGetter = firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source) ? function (itemOpt, dimName, dataIndex, dimIndex) { - // Use dataIndex as ordinal value in categoryAxis - return dimIndex === firstCategoryDimIndex ? dataIndex : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex); - } : null; - data.hasItemOption = false; - data.initData( // Try to reuse the data store in sourceManager if using dataset. - isOriginalSource ? source : store, null, dimValueGetter); - return data; - } - - function isNeedCompleteOrdinalData(source) { - if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) { - var sampleItem = firstDataNotNull(source.data || []); - return !isArray(getDataItemValue(sampleItem)); - } - } - - function firstDataNotNull(arr) { - var i = 0; - - while (i < arr.length && arr[i] == null) { - i++; - } - - return arr[i]; - } - - var Scale = - /** @class */ - function () { - function Scale(setting) { - this._setting = setting || {}; - this._extent = [Infinity, -Infinity]; - } - - Scale.prototype.getSetting = function (name) { - return this._setting[name]; - }; - /** - * Set extent from data - */ - - - Scale.prototype.unionExtent = function (other) { - var extent = this._extent; - other[0] < extent[0] && (extent[0] = other[0]); - other[1] > extent[1] && (extent[1] = other[1]); // not setExtent because in log axis it may transformed to power - // this.setExtent(extent[0], extent[1]); - }; - /** - * Set extent from data - */ - - - Scale.prototype.unionExtentFromData = function (data, dim) { - this.unionExtent(data.getApproximateExtent(dim)); - }; - /** - * Get extent - * - * Extent is always in increase order. - */ - - - Scale.prototype.getExtent = function () { - return this._extent.slice(); - }; - /** - * Set extent - */ - - - Scale.prototype.setExtent = function (start, end) { - var thisExtent = this._extent; - - if (!isNaN(start)) { - thisExtent[0] = start; - } - - if (!isNaN(end)) { - thisExtent[1] = end; - } - }; - /** - * If value is in extent range - */ - - - Scale.prototype.isInExtentRange = function (value) { - return this._extent[0] <= value && this._extent[1] >= value; - }; - /** - * When axis extent depends on data and no data exists, - * axis ticks should not be drawn, which is named 'blank'. - */ - - - Scale.prototype.isBlank = function () { - return this._isBlank; - }; - /** - * When axis extent depends on data and no data exists, - * axis ticks should not be drawn, which is named 'blank'. - */ - - - Scale.prototype.setBlank = function (isBlank) { - this._isBlank = isBlank; - }; - - return Scale; - }(); - - enableClassManagement(Scale); - var uidBase = 0; - - var OrdinalMeta = - /** @class */ - function () { - function OrdinalMeta(opt) { - this.categories = opt.categories || []; - this._needCollect = opt.needCollect; - this._deduplication = opt.deduplication; - this.uid = ++uidBase; - } - - OrdinalMeta.createByAxisModel = function (axisModel) { - var option = axisModel.option; - var data = option.data; - var categories = data && map$1(data, getName); - return new OrdinalMeta({ - categories: categories, - needCollect: !categories, - // deduplication is default in axis. - deduplication: option.dedplication !== false - }); - }; - - OrdinalMeta.prototype.getOrdinal = function (category) { - // @ts-ignore - return this._getOrCreateMap().get(category); - }; - /** - * @return The ordinal. If not found, return NaN. - */ - - - OrdinalMeta.prototype.parseAndCollect = function (category) { - var index; - var needCollect = this._needCollect; // The value of category dim can be the index of the given category set. - // This feature is only supported when !needCollect, because we should - // consider a common case: a value is 2017, which is a number but is - // expected to be tread as a category. This case usually happen in dataset, - // where it happent to be no need of the index feature. - - if (!isString(category) && !needCollect) { - return category; - } // Optimize for the scenario: - // category is ['2012-01-01', '2012-01-02', ...], where the input - // data has been ensured not duplicate and is large data. - // Notice, if a dataset dimension provide categroies, usually echarts - // should remove duplication except user tell echarts dont do that - // (set axis.deduplication = false), because echarts do not know whether - // the values in the category dimension has duplication (consider the - // parallel-aqi example) - - - if (needCollect && !this._deduplication) { - index = this.categories.length; - this.categories[index] = category; - return index; - } - - var map = this._getOrCreateMap(); // @ts-ignore - - - index = map.get(category); - - if (index == null) { - if (needCollect) { - index = this.categories.length; - this.categories[index] = category; // @ts-ignore - - map.set(category, index); - } else { - index = NaN; - } - } - - return index; - }; // Consider big data, do not create map until needed. - - - OrdinalMeta.prototype._getOrCreateMap = function () { - return this._map || (this._map = createHashMap(this.categories)); - }; - - return OrdinalMeta; - }(); - - function getName(obj) { - if (isObject$2(obj) && obj.value != null) { - return obj.value; - } else { - return obj + ''; - } - } - - function isValueNice(val) { - var exp10 = Math.pow(10, quantityExponent(Math.abs(val))); - var f = Math.abs(val / exp10); - return f === 0 || f === 1 || f === 2 || f === 3 || f === 5; - } - - function isIntervalOrLogScale(scale) { - return scale.type === 'interval' || scale.type === 'log'; - } - /** - * @param extent Both extent[0] and extent[1] should be valid number. - * Should be extent[0] < extent[1]. - * @param splitNumber splitNumber should be >= 1. - */ - - - function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) { - var result = {}; - var span = extent[1] - extent[0]; - var interval = result.interval = nice(span / splitNumber, true); - - if (minInterval != null && interval < minInterval) { - interval = result.interval = minInterval; - } - - if (maxInterval != null && interval > maxInterval) { - interval = result.interval = maxInterval; - } // Tow more digital for tick. - - - var precision = result.intervalPrecision = getIntervalPrecision(interval); // Niced extent inside original extent - - var niceTickExtent = result.niceTickExtent = [round$2(Math.ceil(extent[0] / interval) * interval, precision), round$2(Math.floor(extent[1] / interval) * interval, precision)]; - fixExtent(niceTickExtent, extent); - return result; - } - - function increaseInterval(interval) { - var exp10 = Math.pow(10, quantityExponent(interval)); // Increase interval - - var f = interval / exp10; - - if (!f) { - f = 1; - } else if (f === 2) { - f = 3; - } else if (f === 3) { - f = 5; - } else { - // f is 1 or 5 - f *= 2; - } - - return round$2(f * exp10); - } - /** - * @return interval precision - */ - - - function getIntervalPrecision(interval) { - // Tow more digital for tick. - return getPrecision(interval) + 2; - } - - function clamp(niceTickExtent, idx, extent) { - niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]); - } // In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent. - - - function fixExtent(niceTickExtent, extent) { - !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]); - !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]); - clamp(niceTickExtent, 0, extent); - clamp(niceTickExtent, 1, extent); - - if (niceTickExtent[0] > niceTickExtent[1]) { - niceTickExtent[0] = niceTickExtent[1]; - } - } - - function contain$1(val, extent) { - return val >= extent[0] && val <= extent[1]; - } - - function normalize(val, extent) { - if (extent[1] === extent[0]) { - return 0.5; - } - - return (val - extent[0]) / (extent[1] - extent[0]); - } - - function scale(val, extent) { - return val * (extent[1] - extent[0]) + extent[0]; - } - - var OrdinalScale = - /** @class */ - function (_super) { - __extends(OrdinalScale, _super); - - function OrdinalScale(setting) { - var _this = _super.call(this, setting) || this; - - _this.type = 'ordinal'; - - var ordinalMeta = _this.getSetting('ordinalMeta'); // Caution: Should not use instanceof, consider ec-extensions using - // import approach to get OrdinalMeta class. - - - if (!ordinalMeta) { - ordinalMeta = new OrdinalMeta({}); - } - - if (isArray(ordinalMeta)) { - ordinalMeta = new OrdinalMeta({ - categories: map$1(ordinalMeta, function (item) { - return isObject$2(item) ? item.value : item; - }) - }); - } - - _this._ordinalMeta = ordinalMeta; - _this._extent = _this.getSetting('extent') || [0, ordinalMeta.categories.length - 1]; - return _this; - } - - OrdinalScale.prototype.parse = function (val) { - // Caution: Math.round(null) will return `0` rather than `NaN` - if (val == null) { - return NaN; - } - - return isString(val) ? this._ordinalMeta.getOrdinal(val) // val might be float. - : Math.round(val); - }; - - OrdinalScale.prototype.contain = function (rank) { - rank = this.parse(rank); - return contain$1(rank, this._extent) && this._ordinalMeta.categories[rank] != null; - }; - /** - * Normalize given rank or name to linear [0, 1] - * @param val raw ordinal number. - * @return normalized value in [0, 1]. - */ - - - OrdinalScale.prototype.normalize = function (val) { - val = this._getTickNumber(this.parse(val)); - return normalize(val, this._extent); - }; - /** - * @param val normalized value in [0, 1]. - * @return raw ordinal number. - */ - - - OrdinalScale.prototype.scale = function (val) { - val = Math.round(scale(val, this._extent)); - return this.getRawOrdinalNumber(val); - }; - - OrdinalScale.prototype.getTicks = function () { - var ticks = []; - var extent = this._extent; - var rank = extent[0]; - - while (rank <= extent[1]) { - ticks.push({ - value: rank - }); - rank++; - } - - return ticks; - }; - - OrdinalScale.prototype.getMinorTicks = function (splitNumber) { - // Not support. - return; - }; - /** - * @see `Ordinal['_ordinalNumbersByTick']` - */ - - - OrdinalScale.prototype.setSortInfo = function (info) { - if (info == null) { - this._ordinalNumbersByTick = this._ticksByOrdinalNumber = null; - return; - } - - var infoOrdinalNumbers = info.ordinalNumbers; - var ordinalsByTick = this._ordinalNumbersByTick = []; - var ticksByOrdinal = this._ticksByOrdinalNumber = []; // Unnecessary support negative tick in `realtimeSort`. - - var tickNum = 0; - var allCategoryLen = this._ordinalMeta.categories.length; - - for (var len = Math.min(allCategoryLen, infoOrdinalNumbers.length); tickNum < len; ++tickNum) { - var ordinalNumber = infoOrdinalNumbers[tickNum]; - ordinalsByTick[tickNum] = ordinalNumber; - ticksByOrdinal[ordinalNumber] = tickNum; - } // Handle that `series.data` only covers part of the `axis.category.data`. - - - var unusedOrdinal = 0; - - for (; tickNum < allCategoryLen; ++tickNum) { - while (ticksByOrdinal[unusedOrdinal] != null) { - unusedOrdinal++; - } - - ordinalsByTick.push(unusedOrdinal); - ticksByOrdinal[unusedOrdinal] = tickNum; - } - }; - - OrdinalScale.prototype._getTickNumber = function (ordinal) { - var ticksByOrdinalNumber = this._ticksByOrdinalNumber; // also support ordinal out of range of `ordinalMeta.categories.length`, - // where ordinal numbers are used as tick value directly. - - return ticksByOrdinalNumber && ordinal >= 0 && ordinal < ticksByOrdinalNumber.length ? ticksByOrdinalNumber[ordinal] : ordinal; - }; - /** - * @usage - * ```js - * const ordinalNumber = ordinalScale.getRawOrdinalNumber(tickVal); - * - * // case0 - * const rawOrdinalValue = axisModel.getCategories()[ordinalNumber]; - * // case1 - * const rawOrdinalValue = this._ordinalMeta.categories[ordinalNumber]; - * // case2 - * const coord = axis.dataToCoord(ordinalNumber); - * ``` - * - * @param {OrdinalNumber} tickNumber index of display - */ - - - OrdinalScale.prototype.getRawOrdinalNumber = function (tickNumber) { - var ordinalNumbersByTick = this._ordinalNumbersByTick; // tickNumber may be out of range, e.g., when axis max is larger than `ordinalMeta.categories.length`., - // where ordinal numbers are used as tick value directly. - - return ordinalNumbersByTick && tickNumber >= 0 && tickNumber < ordinalNumbersByTick.length ? ordinalNumbersByTick[tickNumber] : tickNumber; - }; - /** - * Get item on tick - */ - - - OrdinalScale.prototype.getLabel = function (tick) { - if (!this.isBlank()) { - var ordinalNumber = this.getRawOrdinalNumber(tick.value); - var cateogry = this._ordinalMeta.categories[ordinalNumber]; // Note that if no data, ordinalMeta.categories is an empty array. - // Return empty if it's not exist. - - return cateogry == null ? '' : cateogry + ''; - } - }; - - OrdinalScale.prototype.count = function () { - return this._extent[1] - this._extent[0] + 1; - }; - - OrdinalScale.prototype.unionExtentFromData = function (data, dim) { - this.unionExtent(data.getApproximateExtent(dim)); - }; - /** - * @override - * If value is in extent range - */ - - - OrdinalScale.prototype.isInExtentRange = function (value) { - value = this._getTickNumber(value); - return this._extent[0] <= value && this._extent[1] >= value; - }; - - OrdinalScale.prototype.getOrdinalMeta = function () { - return this._ordinalMeta; - }; - - OrdinalScale.prototype.calcNiceTicks = function () {}; - - OrdinalScale.prototype.calcNiceExtent = function () {}; - - OrdinalScale.type = 'ordinal'; - return OrdinalScale; - }(Scale); - - Scale.registerClass(OrdinalScale); - var roundNumber = round$2; - - var IntervalScale = - /** @class */ - function (_super) { - __extends(IntervalScale, _super); - - function IntervalScale() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'interval'; // Step is calculated in adjustExtent. - - _this._interval = 0; - _this._intervalPrecision = 2; - return _this; - } - - IntervalScale.prototype.parse = function (val) { - return val; - }; - - IntervalScale.prototype.contain = function (val) { - return contain$1(val, this._extent); - }; - - IntervalScale.prototype.normalize = function (val) { - return normalize(val, this._extent); - }; - - IntervalScale.prototype.scale = function (val) { - return scale(val, this._extent); - }; - - IntervalScale.prototype.setExtent = function (start, end) { - var thisExtent = this._extent; // start,end may be a Number like '25',so... - - if (!isNaN(start)) { - thisExtent[0] = parseFloat(start); - } - - if (!isNaN(end)) { - thisExtent[1] = parseFloat(end); - } - }; - - IntervalScale.prototype.unionExtent = function (other) { - var extent = this._extent; - other[0] < extent[0] && (extent[0] = other[0]); - other[1] > extent[1] && (extent[1] = other[1]); // unionExtent may called by it's sub classes - - this.setExtent(extent[0], extent[1]); - }; - - IntervalScale.prototype.getInterval = function () { - return this._interval; - }; - - IntervalScale.prototype.setInterval = function (interval) { - this._interval = interval; // Dropped auto calculated niceExtent and use user-set extent. - // We assume user wants to set both interval, min, max to get a better result. - - this._niceExtent = this._extent.slice(); - this._intervalPrecision = getIntervalPrecision(interval); - }; - /** - * @param expandToNicedExtent Whether expand the ticks to niced extent. - */ - - - IntervalScale.prototype.getTicks = function (expandToNicedExtent) { - var interval = this._interval; - var extent = this._extent; - var niceTickExtent = this._niceExtent; - var intervalPrecision = this._intervalPrecision; - var ticks = []; // If interval is 0, return []; - - if (!interval) { - return ticks; - } // Consider this case: using dataZoom toolbox, zoom and zoom. - - - var safeLimit = 10000; - - if (extent[0] < niceTickExtent[0]) { - if (expandToNicedExtent) { - ticks.push({ - value: roundNumber(niceTickExtent[0] - interval, intervalPrecision) - }); - } else { - ticks.push({ - value: extent[0] - }); - } - } - - var tick = niceTickExtent[0]; - - while (tick <= niceTickExtent[1]) { - ticks.push({ - value: tick - }); // Avoid rounding error - - tick = roundNumber(tick + interval, intervalPrecision); - - if (tick === ticks[ticks.length - 1].value) { - // Consider out of safe float point, e.g., - // -3711126.9907707 + 2e-10 === -3711126.9907707 - break; - } - - if (ticks.length > safeLimit) { - return []; - } - } // Consider this case: the last item of ticks is smaller - // than niceTickExtent[1] and niceTickExtent[1] === extent[1]. - - - var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceTickExtent[1]; - - if (extent[1] > lastNiceTick) { - if (expandToNicedExtent) { - ticks.push({ - value: roundNumber(lastNiceTick + interval, intervalPrecision) - }); - } else { - ticks.push({ - value: extent[1] - }); - } - } - - return ticks; - }; - - IntervalScale.prototype.getMinorTicks = function (splitNumber) { - var ticks = this.getTicks(true); - var minorTicks = []; - var extent = this.getExtent(); - - for (var i = 1; i < ticks.length; i++) { - var nextTick = ticks[i]; - var prevTick = ticks[i - 1]; - var count = 0; - var minorTicksGroup = []; - var interval = nextTick.value - prevTick.value; - var minorInterval = interval / splitNumber; - - while (count < splitNumber - 1) { - var minorTick = roundNumber(prevTick.value + (count + 1) * minorInterval); // For the first and last interval. The count may be less than splitNumber. - - if (minorTick > extent[0] && minorTick < extent[1]) { - minorTicksGroup.push(minorTick); - } - - count++; - } - - minorTicks.push(minorTicksGroup); - } - - return minorTicks; - }; - /** - * @param opt.precision If 'auto', use nice presision. - * @param opt.pad returns 1.50 but not 1.5 if precision is 2. - */ - - - IntervalScale.prototype.getLabel = function (data, opt) { - if (data == null) { - return ''; - } - - var precision = opt && opt.precision; - - if (precision == null) { - precision = getPrecision(data.value) || 0; - } else if (precision === 'auto') { - // Should be more precise then tick. - precision = this._intervalPrecision; - } // (1) If `precision` is set, 12.005 should be display as '12.00500'. - // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'. - - - var dataNum = roundNumber(data.value, precision, true); - return addCommas(dataNum); - }; - /** - * @param splitNumber By default `5`. - */ - - - IntervalScale.prototype.calcNiceTicks = function (splitNumber, minInterval, maxInterval) { - splitNumber = splitNumber || 5; - var extent = this._extent; - var span = extent[1] - extent[0]; - - if (!isFinite(span)) { - return; - } // User may set axis min 0 and data are all negative - // FIXME If it needs to reverse ? - - - if (span < 0) { - span = -span; - extent.reverse(); - } - - var result = intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval); - this._intervalPrecision = result.intervalPrecision; - this._interval = result.interval; - this._niceExtent = result.niceTickExtent; - }; - - IntervalScale.prototype.calcNiceExtent = function (opt) { - var extent = this._extent; // If extent start and end are same, expand them - - if (extent[0] === extent[1]) { - if (extent[0] !== 0) { - // Expand extent - // Note that extents can be both negative. See #13154 - var expandSize = Math.abs(extent[0]); // In the fowllowing case - // Axis has been fixed max 100 - // Plus data are all 100 and axis extent are [100, 100]. - // Extend to the both side will cause expanded max is larger than fixed max. - // So only expand to the smaller side. - - if (!opt.fixMax) { - extent[1] += expandSize / 2; - extent[0] -= expandSize / 2; - } else { - extent[0] -= expandSize / 2; - } - } else { - extent[1] = 1; - } - } - - var span = extent[1] - extent[0]; // If there are no data and extent are [Infinity, -Infinity] - - if (!isFinite(span)) { - extent[0] = 0; - extent[1] = 1; - } - - this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); // let extent = this._extent; - - var interval = this._interval; - - if (!opt.fixMin) { - extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval); - } - - if (!opt.fixMax) { - extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval); - } - }; - - IntervalScale.prototype.setNiceExtent = function (min, max) { - this._niceExtent = [min, max]; - }; - - IntervalScale.type = 'interval'; - return IntervalScale; - }(Scale); - - Scale.registerClass(IntervalScale); - /* global Float32Array */ - - var supportFloat32Array = typeof Float32Array !== 'undefined'; - var Float32ArrayCtor = !supportFloat32Array ? Array : Float32Array; - - function createFloat32Array(arg) { - if (isArray(arg)) { - // Return self directly if don't support TypedArray. - return supportFloat32Array ? new Float32Array(arg) : arg; - } // Else is number - - - return new Float32ArrayCtor(arg); - } - - var STACK_PREFIX = '__ec_stack_'; - - function getSeriesStackId(seriesModel) { - return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; - } - - function getAxisKey(axis) { - return axis.dim + axis.index; - } - - function prepareLayoutBarSeries(seriesType, ecModel) { - var seriesModels = []; - ecModel.eachSeriesByType(seriesType, function (seriesModel) { - // Check series coordinate, do layout for cartesian2d only - if (isOnCartesian(seriesModel)) { - seriesModels.push(seriesModel); - } - }); - return seriesModels; - } - /** - * Map from (baseAxis.dim + '_' + baseAxis.index) to min gap of two adjacent - * values. - * This works for time axes, value axes, and log axes. - * For a single time axis, return value is in the form like - * {'x_0': [1000000]}. - * The value of 1000000 is in milliseconds. - */ - - - function getValueAxesMinGaps(barSeries) { - /** - * Map from axis.index to values. - * For a single time axis, axisValues is in the form like - * {'x_0': [1495555200000, 1495641600000, 1495728000000]}. - * Items in axisValues[x], e.g. 1495555200000, are time values of all - * series. - */ - var axisValues = {}; - each$4(barSeries, function (seriesModel) { - var cartesian = seriesModel.coordinateSystem; - var baseAxis = cartesian.getBaseAxis(); - - if (baseAxis.type !== 'time' && baseAxis.type !== 'value') { - return; - } - - var data = seriesModel.getData(); - var key = baseAxis.dim + '_' + baseAxis.index; - var dimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); - var store = data.getStore(); - - for (var i = 0, cnt = store.count(); i < cnt; ++i) { - var value = store.get(dimIdx, i); - - if (!axisValues[key]) { - // No previous data for the axis - axisValues[key] = [value]; - } else { - // No value in previous series - axisValues[key].push(value); - } // Ignore duplicated time values in the same axis - - } - }); - var axisMinGaps = {}; - - for (var key in axisValues) { - if (axisValues.hasOwnProperty(key)) { - var valuesInAxis = axisValues[key]; - - if (valuesInAxis) { - // Sort axis values into ascending order to calculate gaps - valuesInAxis.sort(function (a, b) { - return a - b; - }); - var min = null; - - for (var j = 1; j < valuesInAxis.length; ++j) { - var delta = valuesInAxis[j] - valuesInAxis[j - 1]; - - if (delta > 0) { - // Ignore 0 delta because they are of the same axis value - min = min === null ? delta : Math.min(min, delta); - } - } // Set to null if only have one data - - - axisMinGaps[key] = min; - } - } - } - - return axisMinGaps; - } - - function makeColumnLayout(barSeries) { - var axisMinGaps = getValueAxesMinGaps(barSeries); - var seriesInfoList = []; - each$4(barSeries, function (seriesModel) { - var cartesian = seriesModel.coordinateSystem; - var baseAxis = cartesian.getBaseAxis(); - var axisExtent = baseAxis.getExtent(); - var bandWidth; - - if (baseAxis.type === 'category') { - bandWidth = baseAxis.getBandWidth(); - } else if (baseAxis.type === 'value' || baseAxis.type === 'time') { - var key = baseAxis.dim + '_' + baseAxis.index; - var minGap = axisMinGaps[key]; - var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]); - var scale = baseAxis.scale.getExtent(); - var scaleSpan = Math.abs(scale[1] - scale[0]); - bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan; // When there is only one data value - } else { - var data = seriesModel.getData(); - bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); - } - - var barWidth = parsePercent(seriesModel.get('barWidth'), bandWidth); - var barMaxWidth = parsePercent(seriesModel.get('barMaxWidth'), bandWidth); - var barMinWidth = parsePercent( // barMinWidth by default is 0.5 / 1 in cartesian. Because in value axis, - // the auto-calculated bar width might be less than 0.5 / 1. - seriesModel.get('barMinWidth') || (isInLargeMode(seriesModel) ? 0.5 : 1), bandWidth); - var barGap = seriesModel.get('barGap'); - var barCategoryGap = seriesModel.get('barCategoryGap'); - seriesInfoList.push({ - bandWidth: bandWidth, - barWidth: barWidth, - barMaxWidth: barMaxWidth, - barMinWidth: barMinWidth, - barGap: barGap, - barCategoryGap: barCategoryGap, - axisKey: getAxisKey(baseAxis), - stackId: getSeriesStackId(seriesModel) - }); - }); - return doCalBarWidthAndOffset(seriesInfoList); - } - - function doCalBarWidthAndOffset(seriesInfoList) { - // Columns info on each category axis. Key is cartesian name - var columnsMap = {}; - each$4(seriesInfoList, function (seriesInfo, idx) { - var axisKey = seriesInfo.axisKey; - var bandWidth = seriesInfo.bandWidth; - var columnsOnAxis = columnsMap[axisKey] || { - bandWidth: bandWidth, - remainedWidth: bandWidth, - autoWidthCount: 0, - categoryGap: null, - gap: '20%', - stacks: {} - }; - var stacks = columnsOnAxis.stacks; - columnsMap[axisKey] = columnsOnAxis; - var stackId = seriesInfo.stackId; - - if (!stacks[stackId]) { - columnsOnAxis.autoWidthCount++; - } - - stacks[stackId] = stacks[stackId] || { - width: 0, - maxWidth: 0 - }; // Caution: In a single coordinate system, these barGrid attributes - // will be shared by series. Consider that they have default values, - // only the attributes set on the last series will work. - // Do not change this fact unless there will be a break change. - - var barWidth = seriesInfo.barWidth; - - if (barWidth && !stacks[stackId].width) { - // See #6312, do not restrict width. - stacks[stackId].width = barWidth; - barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); - columnsOnAxis.remainedWidth -= barWidth; - } - - var barMaxWidth = seriesInfo.barMaxWidth; - barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); - var barMinWidth = seriesInfo.barMinWidth; - barMinWidth && (stacks[stackId].minWidth = barMinWidth); - var barGap = seriesInfo.barGap; - barGap != null && (columnsOnAxis.gap = barGap); - var barCategoryGap = seriesInfo.barCategoryGap; - barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); - }); - var result = {}; - each$4(columnsMap, function (columnsOnAxis, coordSysName) { - result[coordSysName] = {}; - var stacks = columnsOnAxis.stacks; - var bandWidth = columnsOnAxis.bandWidth; - var categoryGapPercent = columnsOnAxis.categoryGap; - - if (categoryGapPercent == null) { - var columnCount = keys(stacks).length; // More columns in one group - // the spaces between group is smaller. Or the column will be too thin. - - categoryGapPercent = Math.max(35 - columnCount * 4, 15) + '%'; - } - - var categoryGap = parsePercent(categoryGapPercent, bandWidth); - var barGapPercent = parsePercent(columnsOnAxis.gap, 1); - var remainedWidth = columnsOnAxis.remainedWidth; - var autoWidthCount = columnsOnAxis.autoWidthCount; - var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); - autoWidth = Math.max(autoWidth, 0); // Find if any auto calculated bar exceeded maxBarWidth - - each$4(stacks, function (column) { - var maxWidth = column.maxWidth; - var minWidth = column.minWidth; - - if (!column.width) { - var finalWidth = autoWidth; - - if (maxWidth && maxWidth < finalWidth) { - finalWidth = Math.min(maxWidth, remainedWidth); - } // `minWidth` has higher priority. `minWidth` decide that whether the - // bar is able to be visible. So `minWidth` should not be restricted - // by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In - // the extreme cases for `value` axis, bars are allowed to overlap - // with each other if `minWidth` specified. - - - if (minWidth && minWidth > finalWidth) { - finalWidth = minWidth; - } - - if (finalWidth !== autoWidth) { - column.width = finalWidth; - remainedWidth -= finalWidth + barGapPercent * finalWidth; - autoWidthCount--; - } - } else { - // `barMinWidth/barMaxWidth` has higher priority than `barWidth`, as - // CSS does. Because barWidth can be a percent value, where - // `barMaxWidth` can be used to restrict the final width. - var finalWidth = column.width; - - if (maxWidth) { - finalWidth = Math.min(finalWidth, maxWidth); - } // `minWidth` has higher priority, as described above - - - if (minWidth) { - finalWidth = Math.max(finalWidth, minWidth); - } - - column.width = finalWidth; - remainedWidth -= finalWidth + barGapPercent * finalWidth; - autoWidthCount--; - } - }); // Recalculate width again - - autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); - autoWidth = Math.max(autoWidth, 0); - var widthSum = 0; - var lastColumn; - each$4(stacks, function (column, idx) { - if (!column.width) { - column.width = autoWidth; - } - - lastColumn = column; - widthSum += column.width * (1 + barGapPercent); - }); - - if (lastColumn) { - widthSum -= lastColumn.width * barGapPercent; - } - - var offset = -widthSum / 2; - each$4(stacks, function (column, stackId) { - result[coordSysName][stackId] = result[coordSysName][stackId] || { - bandWidth: bandWidth, - offset: offset, - width: column.width - }; - offset += column.width * (1 + barGapPercent); - }); - }); - return result; - } - - function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) { - if (barWidthAndOffset && axis) { - var result = barWidthAndOffset[getAxisKey(axis)]; - - if (result != null && seriesModel != null) { - return result[getSeriesStackId(seriesModel)]; - } - - return result; - } - } - - function layout$1(seriesType, ecModel) { - var seriesModels = prepareLayoutBarSeries(seriesType, ecModel); - var barWidthAndOffset = makeColumnLayout(seriesModels); - each$4(seriesModels, function (seriesModel) { - var data = seriesModel.getData(); - var cartesian = seriesModel.coordinateSystem; - var baseAxis = cartesian.getBaseAxis(); - var stackId = getSeriesStackId(seriesModel); - var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; - var columnOffset = columnLayoutInfo.offset; - var columnWidth = columnLayoutInfo.width; - data.setLayout({ - bandWidth: columnLayoutInfo.bandWidth, - offset: columnOffset, - size: columnWidth - }); - }); - } // TODO: Do not support stack in large mode yet. - - - function createProgressiveLayout(seriesType) { - return { - seriesType: seriesType, - plan: createRenderPlanner(), - reset: function (seriesModel) { - if (!isOnCartesian(seriesModel)) { - return; - } - - var data = seriesModel.getData(); - var cartesian = seriesModel.coordinateSystem; - var baseAxis = cartesian.getBaseAxis(); - var valueAxis = cartesian.getOtherAxis(baseAxis); - var valueDimIdx = data.getDimensionIndex(data.mapDimension(valueAxis.dim)); - var baseDimIdx = data.getDimensionIndex(data.mapDimension(baseAxis.dim)); - var drawBackground = seriesModel.get('showBackground', true); - var valueDim = data.mapDimension(valueAxis.dim); - var stackResultDim = data.getCalculationInfo('stackResultDimension'); - var stacked = isDimensionStacked(data, valueDim) && !!data.getCalculationInfo('stackedOnSeries'); - var isValueAxisH = valueAxis.isHorizontal(); - var valueAxisStart = getValueAxisStart(baseAxis, valueAxis); - var isLarge = isInLargeMode(seriesModel); - var barMinHeight = seriesModel.get('barMinHeight') || 0; - var stackedDimIdx = stackResultDim && data.getDimensionIndex(stackResultDim); // Layout info. - - var columnWidth = data.getLayout('size'); - var columnOffset = data.getLayout('offset'); - return { - progress: function (params, data) { - var count = params.count; - var largePoints = isLarge && createFloat32Array(count * 3); - var largeBackgroundPoints = isLarge && drawBackground && createFloat32Array(count * 3); - var largeDataIndices = isLarge && createFloat32Array(count); - var coordLayout = cartesian.master.getRect(); - var bgSize = isValueAxisH ? coordLayout.width : coordLayout.height; - var dataIndex; - var store = data.getStore(); - var idxOffset = 0; - - while ((dataIndex = params.next()) != null) { - var value = store.get(stacked ? stackedDimIdx : valueDimIdx, dataIndex); - var baseValue = store.get(baseDimIdx, dataIndex); - var baseCoord = valueAxisStart; - var startValue = void 0; // Because of the barMinHeight, we can not use the value in - // stackResultDimension directly. - - if (stacked) { - startValue = +value - store.get(valueDimIdx, dataIndex); - } - - var x = void 0; - var y = void 0; - var width = void 0; - var height = void 0; - - if (isValueAxisH) { - var coord = cartesian.dataToPoint([value, baseValue]); - - if (stacked) { - var startCoord = cartesian.dataToPoint([startValue, baseValue]); - baseCoord = startCoord[0]; - } - - x = baseCoord; - y = coord[1] + columnOffset; - width = coord[0] - baseCoord; - height = columnWidth; - - if (Math.abs(width) < barMinHeight) { - width = (width < 0 ? -1 : 1) * barMinHeight; - } - } else { - var coord = cartesian.dataToPoint([baseValue, value]); - - if (stacked) { - var startCoord = cartesian.dataToPoint([baseValue, startValue]); - baseCoord = startCoord[1]; - } - - x = coord[0] + columnOffset; - y = baseCoord; - width = columnWidth; - height = coord[1] - baseCoord; - - if (Math.abs(height) < barMinHeight) { - // Include zero to has a positive bar - height = (height <= 0 ? -1 : 1) * barMinHeight; - } - } - - if (!isLarge) { - data.setItemLayout(dataIndex, { - x: x, - y: y, - width: width, - height: height - }); - } else { - largePoints[idxOffset] = x; - largePoints[idxOffset + 1] = y; - largePoints[idxOffset + 2] = isValueAxisH ? width : height; - - if (largeBackgroundPoints) { - largeBackgroundPoints[idxOffset] = isValueAxisH ? coordLayout.x : x; - largeBackgroundPoints[idxOffset + 1] = isValueAxisH ? y : coordLayout.y; - largeBackgroundPoints[idxOffset + 2] = bgSize; - } - - largeDataIndices[dataIndex] = dataIndex; - } - - idxOffset += 3; - } - - if (isLarge) { - data.setLayout({ - largePoints: largePoints, - largeDataIndices: largeDataIndices, - largeBackgroundPoints: largeBackgroundPoints, - valueAxisHorizontal: isValueAxisH - }); - } - } - }; - } - }; - } - - function isOnCartesian(seriesModel) { - return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d'; - } - - function isInLargeMode(seriesModel) { - return seriesModel.pipelineContext && seriesModel.pipelineContext.large; - } // See cases in `test/bar-start.html` and `#7412`, `#8747`. - - - function getValueAxisStart(baseAxis, valueAxis) { - return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0)); - } // FIXME 公用? - - - var bisect = function (a, x, lo, hi) { - while (lo < hi) { - var mid = lo + hi >>> 1; - - if (a[mid][1] < x) { - lo = mid + 1; - } else { - hi = mid; - } - } - - return lo; - }; - - var TimeScale = - /** @class */ - function (_super) { - __extends(TimeScale, _super); - - function TimeScale(settings) { - var _this = _super.call(this, settings) || this; - - _this.type = 'time'; - return _this; - } - /** - * Get label is mainly for other components like dataZoom, tooltip. - */ - - - TimeScale.prototype.getLabel = function (tick) { - var useUTC = this.getSetting('useUTC'); - return format$1(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, useUTC, this.getSetting('locale')); - }; - - TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) { - var isUTC = this.getSetting('useUTC'); - var lang = this.getSetting('locale'); - return leveledFormat(tick, idx, labelFormatter, lang, isUTC); - }; - /** - * @override - */ - - - TimeScale.prototype.getTicks = function () { - var interval = this._interval; - var extent = this._extent; - var ticks = []; // If interval is 0, return []; - - if (!interval) { - return ticks; - } - - ticks.push({ - value: extent[0], - level: 0 - }); - var useUTC = this.getSetting('useUTC'); - var innerTicks = getIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent); - ticks = ticks.concat(innerTicks); - ticks.push({ - value: extent[1], - level: 0 - }); - return ticks; - }; - - TimeScale.prototype.calcNiceExtent = function (opt) { - var extent = this._extent; // If extent start and end are same, expand them - - if (extent[0] === extent[1]) { - // Expand extent - extent[0] -= ONE_DAY; - extent[1] += ONE_DAY; - } // If there are no data and extent are [Infinity, -Infinity] - - - if (extent[1] === -Infinity && extent[0] === Infinity) { - var d = new Date(); - extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); - extent[0] = extent[1] - ONE_DAY; - } - - this.calcNiceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); - }; - - TimeScale.prototype.calcNiceTicks = function (approxTickNum, minInterval, maxInterval) { - approxTickNum = approxTickNum || 10; - var extent = this._extent; - var span = extent[1] - extent[0]; - this._approxInterval = span / approxTickNum; - - if (minInterval != null && this._approxInterval < minInterval) { - this._approxInterval = minInterval; - } - - if (maxInterval != null && this._approxInterval > maxInterval) { - this._approxInterval = maxInterval; - } - - var scaleIntervalsLen = scaleIntervals.length; - var idx = Math.min(bisect(scaleIntervals, this._approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1); // Interval that can be used to calculate ticks - - this._interval = scaleIntervals[idx][1]; // Min level used when picking ticks from top down. - // We check one more level to avoid the ticks are to sparse in some case. - - this._minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0]; - }; - - TimeScale.prototype.parse = function (val) { - // val might be float. - return isNumber(val) ? val : +parseDate(val); - }; - - TimeScale.prototype.contain = function (val) { - return contain$1(this.parse(val), this._extent); - }; - - TimeScale.prototype.normalize = function (val) { - return normalize(this.parse(val), this._extent); - }; - - TimeScale.prototype.scale = function (val) { - return scale(val, this._extent); - }; - - TimeScale.type = 'time'; - return TimeScale; - }(IntervalScale); - /** - * This implementation was originally copied from "d3.js" - * - * with some modifications made for this program. - * See the license statement at the head of this file. - */ - - - var scaleIntervals = [// Format interval - ['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR] // 1Y - ]; - - function isUnitValueSame(unit, valueA, valueB, isUTC) { - var dateA = parseDate(valueA); - var dateB = parseDate(valueB); - - var isSame = function (unit) { - return getUnitValue(dateA, unit, isUTC) === getUnitValue(dateB, unit, isUTC); - }; - - var isSameYear = function () { - return isSame('year'); - }; // const isSameHalfYear = () => isSameYear() && isSame('half-year'); - // const isSameQuater = () => isSameYear() && isSame('quarter'); - - - var isSameMonth = function () { - return isSameYear() && isSame('month'); - }; - - var isSameDay = function () { - return isSameMonth() && isSame('day'); - }; // const isSameHalfDay = () => isSameDay() && isSame('half-day'); - - - var isSameHour = function () { - return isSameDay() && isSame('hour'); - }; - - var isSameMinute = function () { - return isSameHour() && isSame('minute'); - }; - - var isSameSecond = function () { - return isSameMinute() && isSame('second'); - }; - - var isSameMilliSecond = function () { - return isSameSecond() && isSame('millisecond'); - }; - - switch (unit) { - case 'year': - return isSameYear(); - - case 'month': - return isSameMonth(); - - case 'day': - return isSameDay(); - - case 'hour': - return isSameHour(); - - case 'minute': - return isSameMinute(); - - case 'second': - return isSameSecond(); - - case 'millisecond': - return isSameMilliSecond(); - } - } // const primaryUnitGetters = { - // year: fullYearGetterName(), - // month: monthGetterName(), - // day: dateGetterName(), - // hour: hoursGetterName(), - // minute: minutesGetterName(), - // second: secondsGetterName(), - // millisecond: millisecondsGetterName() - // }; - // const primaryUnitUTCGetters = { - // year: fullYearGetterName(true), - // month: monthGetterName(true), - // day: dateGetterName(true), - // hour: hoursGetterName(true), - // minute: minutesGetterName(true), - // second: secondsGetterName(true), - // millisecond: millisecondsGetterName(true) - // }; - // function moveTick(date: Date, unitName: TimeUnit, step: number, isUTC: boolean) { - // step = step || 1; - // switch (getPrimaryTimeUnit(unitName)) { - // case 'year': - // date[fullYearSetterName(isUTC)](date[fullYearGetterName(isUTC)]() + step); - // break; - // case 'month': - // date[monthSetterName(isUTC)](date[monthGetterName(isUTC)]() + step); - // break; - // case 'day': - // date[dateSetterName(isUTC)](date[dateGetterName(isUTC)]() + step); - // break; - // case 'hour': - // date[hoursSetterName(isUTC)](date[hoursGetterName(isUTC)]() + step); - // break; - // case 'minute': - // date[minutesSetterName(isUTC)](date[minutesGetterName(isUTC)]() + step); - // break; - // case 'second': - // date[secondsSetterName(isUTC)](date[secondsGetterName(isUTC)]() + step); - // break; - // case 'millisecond': - // date[millisecondsSetterName(isUTC)](date[millisecondsGetterName(isUTC)]() + step); - // break; - // } - // return date.getTime(); - // } - // const DATE_INTERVALS = [[8, 7.5], [4, 3.5], [2, 1.5]]; - // const MONTH_INTERVALS = [[6, 5.5], [3, 2.5], [2, 1.5]]; - // const MINUTES_SECONDS_INTERVALS = [[30, 30], [20, 20], [15, 15], [10, 10], [5, 5], [2, 2]]; - - - function getDateInterval(approxInterval, daysInMonth) { - approxInterval /= ONE_DAY; - return approxInterval > 16 ? 16 // Math.floor(daysInMonth / 2) + 1 // In this case we only want one tick between two months. - : approxInterval > 7.5 ? 7 // TODO week 7 or day 8? - : approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1; - } - - function getMonthInterval(approxInterval) { - var APPROX_ONE_MONTH = 30 * ONE_DAY; - approxInterval /= APPROX_ONE_MONTH; - return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1; - } - - function getHourInterval(approxInterval) { - approxInterval /= ONE_HOUR; - return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1; - } - - function getMinutesAndSecondsInterval(approxInterval, isMinutes) { - approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND; - return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1; - } - - function getMillisecondsInterval(approxInterval) { - return nice(approxInterval, true); - } - - function getFirstTimestampOfUnit(date, unitName, isUTC) { - var outDate = new Date(date); - - switch (getPrimaryTimeUnit(unitName)) { - case 'year': - case 'month': - outDate[monthSetterName(isUTC)](0); - - case 'day': - outDate[dateSetterName(isUTC)](1); - - case 'hour': - outDate[hoursSetterName(isUTC)](0); - - case 'minute': - outDate[minutesSetterName(isUTC)](0); - - case 'second': - outDate[secondsSetterName(isUTC)](0); - outDate[millisecondsSetterName(isUTC)](0); - } - - return outDate.getTime(); - } - - function getIntervalTicks(bottomUnitName, approxInterval, isUTC, extent) { - var safeLimit = 10000; - var unitNames = timeUnits; - var iter = 0; - - function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) { - var date = new Date(minTimestamp); - var dateTime = minTimestamp; - var d = date[getMethodName](); // if (isDate) { - // d -= 1; // Starts with 0; PENDING - // } - - while (dateTime < maxTimestamp && dateTime <= extent[1]) { - out.push({ - value: dateTime - }); - d += interval; - date[setMethodName](d); - dateTime = date.getTime(); - } // This extra tick is for calcuating ticks of next level. Will not been added to the final result - - - out.push({ - value: dateTime, - notAdd: true - }); - } - - function addLevelTicks(unitName, lastLevelTicks, levelTicks) { - var newAddedTicks = []; - var isFirstLevel = !lastLevelTicks.length; - - if (isUnitValueSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) { - return; - } - - if (isFirstLevel) { - lastLevelTicks = [{ - // TODO Optimize. Not include so may ticks. - value: getFirstTimestampOfUnit(new Date(extent[0]), unitName, isUTC) - }, { - value: extent[1] - }]; - } - - for (var i = 0; i < lastLevelTicks.length - 1; i++) { - var startTick = lastLevelTicks[i].value; - var endTick = lastLevelTicks[i + 1].value; - - if (startTick === endTick) { - continue; - } - - var interval = void 0; - var getterName = void 0; - var setterName = void 0; - var isDate = false; - - switch (unitName) { - case 'year': - interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365)); - getterName = fullYearGetterName(isUTC); - setterName = fullYearSetterName(isUTC); - break; - - case 'half-year': - case 'quarter': - case 'month': - interval = getMonthInterval(approxInterval); - getterName = monthGetterName(isUTC); - setterName = monthSetterName(isUTC); - break; - - case 'week': // PENDING If week is added. Ignore day. - - case 'half-week': - case 'day': - interval = getDateInterval(approxInterval); // Use 32 days and let interval been 16 - - getterName = dateGetterName(isUTC); - setterName = dateSetterName(isUTC); - isDate = true; - break; - - case 'half-day': - case 'quarter-day': - case 'hour': - interval = getHourInterval(approxInterval); - getterName = hoursGetterName(isUTC); - setterName = hoursSetterName(isUTC); - break; - - case 'minute': - interval = getMinutesAndSecondsInterval(approxInterval, true); - getterName = minutesGetterName(isUTC); - setterName = minutesSetterName(isUTC); - break; - - case 'second': - interval = getMinutesAndSecondsInterval(approxInterval, false); - getterName = secondsGetterName(isUTC); - setterName = secondsSetterName(isUTC); - break; - - case 'millisecond': - interval = getMillisecondsInterval(approxInterval); - getterName = millisecondsGetterName(isUTC); - setterName = millisecondsSetterName(isUTC); - break; - } - - addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks); - - if (unitName === 'year' && levelTicks.length > 1 && i === 0) { - // Add nearest years to the left extent. - levelTicks.unshift({ - value: levelTicks[0].value - interval - }); - } - } - - for (var i = 0; i < newAddedTicks.length; i++) { - levelTicks.push(newAddedTicks[i]); - } // newAddedTicks.length && console.log(unitName, newAddedTicks); - - - return newAddedTicks; - } - - var levelsTicks = []; - var currentLevelTicks = []; - var tickCount = 0; - var lastLevelTickCount = 0; - - for (var i = 0; i < unitNames.length && iter++ < safeLimit; ++i) { - var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]); - - if (!isPrimaryTimeUnit(unitNames[i])) { - // TODO - continue; - } - - addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks); - var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null; - - if (primaryTimeUnit !== nextPrimaryTimeUnit) { - if (currentLevelTicks.length) { - lastLevelTickCount = tickCount; // Remove the duplicate so the tick count can be precisely. - - currentLevelTicks.sort(function (a, b) { - return a.value - b.value; - }); - var levelTicksRemoveDuplicated = []; - - for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) { - var tickValue = currentLevelTicks[i_1].value; - - if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) { - levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]); - - if (tickValue >= extent[0] && tickValue <= extent[1]) { - tickCount++; - } - } - } - - var targetTickNum = (extent[1] - extent[0]) / approxInterval; // Added too much in this level and not too less in last level - - if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) { - break; - } // Only treat primary time unit as one level. - - - levelsTicks.push(levelTicksRemoveDuplicated); - - if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) { - break; - } - } // Reset if next unitName is primary - - - currentLevelTicks = []; - } - } - - { - if (iter >= safeLimit) { - warn('Exceed safe limit.'); - } - } - var levelsTicksInExtent = filter(map$1(levelsTicks, function (levelTicks) { - return filter(levelTicks, function (tick) { - return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd; - }); - }), function (levelTicks) { - return levelTicks.length > 0; - }); - var ticks = []; - var maxLevel = levelsTicksInExtent.length - 1; - - for (var i = 0; i < levelsTicksInExtent.length; ++i) { - var levelTicks = levelsTicksInExtent[i]; - - for (var k = 0; k < levelTicks.length; ++k) { - ticks.push({ - value: levelTicks[k].value, - level: maxLevel - i - }); - } - } - - ticks.sort(function (a, b) { - return a.value - b.value; - }); // Remove duplicates - - var result = []; - - for (var i = 0; i < ticks.length; ++i) { - if (i === 0 || ticks[i].value !== ticks[i - 1].value) { - result.push(ticks[i]); - } - } - - return result; - } - - Scale.registerClass(TimeScale); - var scaleProto = Scale.prototype; // FIXME:TS refactor: not good to call it directly with `this`? - - var intervalScaleProto = IntervalScale.prototype; - var roundingErrorFix = round$2; - var mathFloor = Math.floor; - var mathCeil = Math.ceil; - var mathPow = Math.pow; - var mathLog$1 = Math.log; - - var LogScale = - /** @class */ - function (_super) { - __extends(LogScale, _super); - - function LogScale() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'log'; - _this.base = 10; - _this._originalScale = new IntervalScale(); // FIXME:TS actually used by `IntervalScale` - - _this._interval = 0; - return _this; - } - /** - * @param Whether expand the ticks to niced extent. - */ - - - LogScale.prototype.getTicks = function (expandToNicedExtent) { - var originalScale = this._originalScale; - var extent = this._extent; - var originalExtent = originalScale.getExtent(); - var ticks = intervalScaleProto.getTicks.call(this, expandToNicedExtent); - return map$1(ticks, function (tick) { - var val = tick.value; - var powVal = round$2(mathPow(this.base, val)); // Fix #4158 - - powVal = val === extent[0] && this._fixMin ? fixRoundingError(powVal, originalExtent[0]) : powVal; - powVal = val === extent[1] && this._fixMax ? fixRoundingError(powVal, originalExtent[1]) : powVal; - return { - value: powVal - }; - }, this); - }; - - LogScale.prototype.setExtent = function (start, end) { - var base = mathLog$1(this.base); // log(-Infinity) is NaN, so safe guard here - - start = mathLog$1(Math.max(0, start)) / base; - end = mathLog$1(Math.max(0, end)) / base; - intervalScaleProto.setExtent.call(this, start, end); - }; - /** - * @return {number} end - */ - - - LogScale.prototype.getExtent = function () { - var base = this.base; - var extent = scaleProto.getExtent.call(this); - extent[0] = mathPow(base, extent[0]); - extent[1] = mathPow(base, extent[1]); // Fix #4158 - - var originalScale = this._originalScale; - var originalExtent = originalScale.getExtent(); - this._fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0])); - this._fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1])); - return extent; - }; - - LogScale.prototype.unionExtent = function (extent) { - this._originalScale.unionExtent(extent); - - var base = this.base; - extent[0] = mathLog$1(extent[0]) / mathLog$1(base); - extent[1] = mathLog$1(extent[1]) / mathLog$1(base); - scaleProto.unionExtent.call(this, extent); - }; - - LogScale.prototype.unionExtentFromData = function (data, dim) { - // TODO - // filter value that <= 0 - this.unionExtent(data.getApproximateExtent(dim)); - }; - /** - * Update interval and extent of intervals for nice ticks - * @param approxTickNum default 10 Given approx tick number - */ - - - LogScale.prototype.calcNiceTicks = function (approxTickNum) { - approxTickNum = approxTickNum || 10; - var extent = this._extent; - var span = extent[1] - extent[0]; - - if (span === Infinity || span <= 0) { - return; - } - - var interval = quantity(span); - var err = approxTickNum / span * interval; // Filter ticks to get closer to the desired count. - - if (err <= 0.5) { - interval *= 10; - } // Interval should be integer - - - while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) { - interval *= 10; - } - - var niceExtent = [round$2(mathCeil(extent[0] / interval) * interval), round$2(mathFloor(extent[1] / interval) * interval)]; - this._interval = interval; - this._niceExtent = niceExtent; - }; - - LogScale.prototype.calcNiceExtent = function (opt) { - intervalScaleProto.calcNiceExtent.call(this, opt); - this._fixMin = opt.fixMin; - this._fixMax = opt.fixMax; - }; - - LogScale.prototype.parse = function (val) { - return val; - }; - - LogScale.prototype.contain = function (val) { - val = mathLog$1(val) / mathLog$1(this.base); - return contain$1(val, this._extent); - }; - - LogScale.prototype.normalize = function (val) { - val = mathLog$1(val) / mathLog$1(this.base); - return normalize(val, this._extent); - }; - - LogScale.prototype.scale = function (val) { - val = scale(val, this._extent); - return mathPow(this.base, val); - }; - - LogScale.type = 'log'; - return LogScale; - }(Scale); - - var proto = LogScale.prototype; - proto.getMinorTicks = intervalScaleProto.getMinorTicks; - proto.getLabel = intervalScaleProto.getLabel; - - function fixRoundingError(val, originalVal) { - return roundingErrorFix(val, getPrecision(originalVal)); - } - - Scale.registerClass(LogScale); - - var ScaleRawExtentInfo = - /** @class */ - function () { - function ScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis. - originalExtent) { - this._prepareParams(scale, model, originalExtent); - } - /** - * Parameters depending on outside (like model, user callback) - * are prepared and fixed here. - */ - - - ScaleRawExtentInfo.prototype._prepareParams = function (scale, model, // Usually: data extent from all series on this axis. - dataExtent) { - if (dataExtent[1] < dataExtent[0]) { - dataExtent = [NaN, NaN]; - } - - this._dataMin = dataExtent[0]; - this._dataMax = dataExtent[1]; - var isOrdinal = this._isOrdinal = scale.type === 'ordinal'; - this._needCrossZero = scale.type === 'interval' && model.getNeedCrossZero && model.getNeedCrossZero(); - var modelMinRaw = this._modelMinRaw = model.get('min', true); - - if (isFunction(modelMinRaw)) { - // This callback always provides users the full data extent (before data is filtered). - this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({ - min: dataExtent[0], - max: dataExtent[1] - })); - } else if (modelMinRaw !== 'dataMin') { - this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw); - } - - var modelMaxRaw = this._modelMaxRaw = model.get('max', true); - - if (isFunction(modelMaxRaw)) { - // This callback always provides users the full data extent (before data is filtered). - this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({ - min: dataExtent[0], - max: dataExtent[1] - })); - } else if (modelMaxRaw !== 'dataMax') { - this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw); - } - - if (isOrdinal) { - // FIXME: there is a flaw here: if there is no "block" data processor like `dataZoom`, - // and progressive rendering is using, here the category result might just only contain - // the processed chunk rather than the entire result. - this._axisDataLen = model.getCategories().length; - } else { - var boundaryGap = model.get('boundaryGap'); - var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0]; - - if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') { - { - console.warn('Boolean type for boundaryGap is only ' + 'allowed for ordinal axis. Please use string in ' + 'percentage instead, e.g., "20%". Currently, ' + 'boundaryGap is set to be 0.'); - } - this._boundaryGapInner = [0, 0]; - } else { - this._boundaryGapInner = [parsePercent$1(boundaryGapArr[0], 1), parsePercent$1(boundaryGapArr[1], 1)]; - } - } - }; - /** - * Calculate extent by prepared parameters. - * This method has no external dependency and can be called duplicatedly, - * getting the same result. - * If parameters changed, should call this method to recalcuate. - */ - - - ScaleRawExtentInfo.prototype.calculate = function () { - // Notice: When min/max is not set (that is, when there are null/undefined, - // which is the most common case), these cases should be ensured: - // (1) For 'ordinal', show all axis.data. - // (2) For others: - // + `boundaryGap` is applied (if min/max set, boundaryGap is - // disabled). - // + If `needCrossZero`, min/max should be zero, otherwise, min/max should - // be the result that originalExtent enlarged by boundaryGap. - // (3) If no data, it should be ensured that `scale.setBlank` is set. - var isOrdinal = this._isOrdinal; - var dataMin = this._dataMin; - var dataMax = this._dataMax; - var axisDataLen = this._axisDataLen; - var boundaryGapInner = this._boundaryGapInner; - var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null; // Currently if a `'value'` axis model min is specified as 'dataMin'/'dataMax', - // `boundaryGap` will not be used. It's the different from specifying as `null`/`undefined`. - - var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum; - var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum; // If `_modelMinNum`/`_modelMaxNum` is `null`/`undefined`, should not be fixed. - - var minFixed = min != null; - var maxFixed = max != null; - - if (min == null) { - min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span; - } - - if (max == null) { - max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span; - } - - (min == null || !isFinite(min)) && (min = NaN); - (max == null || !isFinite(max)) && (max = NaN); - var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen; // If data extent modified, need to recalculated to ensure cross zero. - - if (this._needCrossZero) { - // Axis is over zero and min is not set - if (min > 0 && max > 0 && !minFixed) { - min = 0; // minFixed = true; - } // Axis is under zero and max is not set - - - if (min < 0 && max < 0 && !maxFixed) { - max = 0; // maxFixed = true; - } // PENDING: - // When `needCrossZero` and all data is positive/negative, should it be ensured - // that the results processed by boundaryGap are positive/negative? - // If so, here `minFixed`/`maxFixed` need to be set. - - } - - var determinedMin = this._determinedMin; - var determinedMax = this._determinedMax; - - if (determinedMin != null) { - min = determinedMin; - minFixed = true; - } - - if (determinedMax != null) { - max = determinedMax; - maxFixed = true; - } // Ensure min/max be finite number or NaN here. (not to be null/undefined) - // `NaN` means min/max axis is blank. - - - return { - min: min, - max: max, - minFixed: minFixed, - maxFixed: maxFixed, - isBlank: isBlank - }; - }; - - ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) { - { - assert(!this.frozen); - } - this[DATA_MIN_MAX_ATTR[minMaxName]] = val; - }; - - ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) { - var attr = DETERMINED_MIN_MAX_ATTR[minMaxName]; - { - assert(!this.frozen // Earse them usually means logic flaw. - && this[attr] == null); - } - this[attr] = val; - }; - - ScaleRawExtentInfo.prototype.freeze = function () { - // @ts-ignore - this.frozen = true; - }; - - return ScaleRawExtentInfo; - }(); - - var DETERMINED_MIN_MAX_ATTR = { - min: '_determinedMin', - max: '_determinedMax' - }; - var DATA_MIN_MAX_ATTR = { - min: '_dataMin', - max: '_dataMax' - }; - /** - * Get scale min max and related info only depends on model settings. - * This method can be called after coordinate system created. - * For example, in data processing stage. - * - * Scale extent info probably be required multiple times during a workflow. - * For example: - * (1) `dataZoom` depends it to get the axis extent in "100%" state. - * (2) `processor/extentCalculator` depends it to make sure whether axis extent is specified. - * (3) `coordSys.update` use it to finally decide the scale extent. - * But the callback of `min`/`max` should not be called multiple times. - * The code below should not be implemented repeatedly either. - * So we cache the result in the scale instance, which will be recreated at the beginning - * of the workflow (because `scale` instance will be recreated each round of the workflow). - */ - - function ensureScaleRawExtentInfo(scale, model, // Usually: data extent from all series on this axis. - originalExtent) { - // Do not permit to recreate. - var rawExtentInfo = scale.rawExtentInfo; - - if (rawExtentInfo) { - return rawExtentInfo; - } - - rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent); // @ts-ignore - - scale.rawExtentInfo = rawExtentInfo; - return rawExtentInfo; - } - - function parseAxisModelMinMax(scale, minMax) { - return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax); - } - /** - * Get axis scale extent before niced. - * Item of returned array can only be number (including Infinity and NaN). - * - * Caution: - * Precondition of calling this method: - * The scale extent has been initialized using series data extent via - * `scale.setExtent` or `scale.unionExtentFromData`; - */ - - - function getScaleExtent(scale, model) { - var scaleType = scale.type; - var rawExtentResult = ensureScaleRawExtentInfo(scale, model, scale.getExtent()).calculate(); - scale.setBlank(rawExtentResult.isBlank); - var min = rawExtentResult.min; - var max = rawExtentResult.max; // If bars are placed on a base axis of type time or interval account for axis boundary overflow and current axis - // is base axis - // FIXME - // (1) Consider support value axis, where below zero and axis `onZero` should be handled properly. - // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent? - // Should not depend on series type `bar`? - // (3) Fix that might overlap when using dataZoom. - // (4) Consider other chart types using `barGrid`? - // See #6728, #4862, `test/bar-overflow-time-plot.html` - - var ecModel = model.ecModel; - - if (ecModel && scaleType === 'time' - /* || scaleType === 'interval' */ - ) { - var barSeriesModels = prepareLayoutBarSeries('bar', ecModel); - var isBaseAxisAndHasBarSeries_1 = false; - each$4(barSeriesModels, function (seriesModel) { - isBaseAxisAndHasBarSeries_1 = isBaseAxisAndHasBarSeries_1 || seriesModel.getBaseAxis() === model.axis; - }); - - if (isBaseAxisAndHasBarSeries_1) { - // Calculate placement of bars on axis. TODO should be decoupled - // with barLayout - var barWidthAndOffset = makeColumnLayout(barSeriesModels); // Adjust axis min and max to account for overflow - - var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset); - min = adjustedScale.min; - max = adjustedScale.max; - } - } - - return { - extent: [min, max], - // "fix" means "fixed", the value should not be - // changed in the subsequent steps. - fixMin: rawExtentResult.minFixed, - fixMax: rawExtentResult.maxFixed - }; - } - - function adjustScaleForOverflow(min, max, model, // Only support cartesian coord yet. - barWidthAndOffset) { - // Get Axis Length - var axisExtent = model.axis.getExtent(); - var axisLength = axisExtent[1] - axisExtent[0]; // Get bars on current base axis and calculate min and max overflow - - var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis); - - if (barsOnCurrentAxis === undefined) { - return { - min: min, - max: max - }; - } - - var minOverflow = Infinity; - each$4(barsOnCurrentAxis, function (item) { - minOverflow = Math.min(item.offset, minOverflow); - }); - var maxOverflow = -Infinity; - each$4(barsOnCurrentAxis, function (item) { - maxOverflow = Math.max(item.offset + item.width, maxOverflow); - }); - minOverflow = Math.abs(minOverflow); - maxOverflow = Math.abs(maxOverflow); - var totalOverFlow = minOverflow + maxOverflow; // Calculate required buffer based on old range and overflow - - var oldRange = max - min; - var oldRangePercentOfNew = 1 - (minOverflow + maxOverflow) / axisLength; - var overflowBuffer = oldRange / oldRangePercentOfNew - oldRange; - max += overflowBuffer * (maxOverflow / totalOverFlow); - min -= overflowBuffer * (minOverflow / totalOverFlow); - return { - min: min, - max: max - }; - } // Precondition of calling this method: - // The scale extent has been initialized using series data extent via - // `scale.setExtent` or `scale.unionExtentFromData`; - - - function niceScaleExtent(scale, inModel) { - var model = inModel; - var extentInfo = getScaleExtent(scale, model); - var extent = extentInfo.extent; - var splitNumber = model.get('splitNumber'); - - if (scale instanceof LogScale) { - scale.base = model.get('logBase'); - } - - var scaleType = scale.type; - var interval = model.get('interval'); - var isIntervalOrTime = scaleType === 'interval' || scaleType === 'time'; - scale.setExtent(extent[0], extent[1]); - scale.calcNiceExtent({ - splitNumber: splitNumber, - fixMin: extentInfo.fixMin, - fixMax: extentInfo.fixMax, - minInterval: isIntervalOrTime ? model.get('minInterval') : null, - maxInterval: isIntervalOrTime ? model.get('maxInterval') : null - }); // If some one specified the min, max. And the default calculated interval - // is not good enough. He can specify the interval. It is often appeared - // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard - // to be 60. - // FIXME - - if (interval != null) { - scale.setInterval && scale.setInterval(interval); - } - } - /** - * @param axisType Default retrieve from model.type - */ - - - function createScaleByModel(model, axisType) { - axisType = axisType || model.get('type'); - - if (axisType) { - switch (axisType) { - // Buildin scale - case 'category': - return new OrdinalScale({ - ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(), - extent: [Infinity, -Infinity] - }); - - case 'time': - return new TimeScale({ - locale: model.ecModel.getLocaleModel(), - useUTC: model.ecModel.get('useUTC') - }); - - default: - // case 'value'/'interval', 'log', or others. - return new (Scale.getClass(axisType) || IntervalScale)(); - } - } - } - /** - * Check if the axis cross 0 - */ - - - function ifAxisCrossZero(axis) { - var dataExtent = axis.scale.getExtent(); - var min = dataExtent[0]; - var max = dataExtent[1]; - return !(min > 0 && max > 0 || min < 0 && max < 0); - } - /** - * @param axis - * @return Label formatter function. - * param: {number} tickValue, - * param: {number} idx, the index in all ticks. - * If category axis, this param is not required. - * return: {string} label string. - */ - - - function makeLabelFormatter(axis) { - var labelFormatter = axis.getLabelModel().get('formatter'); - var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null; - - if (axis.scale.type === 'time') { - return function (tpl) { - return function (tick, idx) { - return axis.scale.getFormattedLabel(tick, idx, tpl); - }; - }(labelFormatter); - } else if (isString(labelFormatter)) { - return function (tpl) { - return function (tick) { - // For category axis, get raw value; for numeric axis, - // get formatted label like '1,333,444'. - var label = axis.scale.getLabel(tick); - var text = tpl.replace('{value}', label != null ? label : ''); - return text; - }; - }(labelFormatter); - } else if (isFunction(labelFormatter)) { - return function (cb) { - return function (tick, idx) { - // The original intention of `idx` is "the index of the tick in all ticks". - // But the previous implementation of category axis do not consider the - // `axisLabel.interval`, which cause that, for example, the `interval` is - // `1`, then the ticks "name5", "name7", "name9" are displayed, where the - // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep - // the definition here for back compatibility. - if (categoryTickStart != null) { - idx = tick.value - categoryTickStart; - } - - return cb(getAxisRawValue(axis, tick), idx, tick.level != null ? { - level: tick.level - } : null); - }; - }(labelFormatter); - } else { - return function (tick) { - return axis.scale.getLabel(tick); - }; - } - } - - function getAxisRawValue(axis, tick) { - // In category axis with data zoom, tick is not the original - // index of axis.data. So tick should not be exposed to user - // in category axis. - return axis.type === 'category' ? axis.scale.getLabel(tick) : tick.value; - } - /** - * @param axis - * @return Be null/undefined if no labels. - */ - - - function estimateLabelUnionRect(axis) { - var axisModel = axis.model; - var scale = axis.scale; - - if (!axisModel.get(['axisLabel', 'show']) || scale.isBlank()) { - return; - } - - var realNumberScaleTicks; - var tickCount; - var categoryScaleExtent = scale.getExtent(); // Optimize for large category data, avoid call `getTicks()`. - - if (scale instanceof OrdinalScale) { - tickCount = scale.count(); - } else { - realNumberScaleTicks = scale.getTicks(); - tickCount = realNumberScaleTicks.length; - } - - var axisLabelModel = axis.getLabelModel(); - var labelFormatter = makeLabelFormatter(axis); - var rect; - var step = 1; // Simple optimization for large amount of labels - - if (tickCount > 40) { - step = Math.ceil(tickCount / 40); - } - - for (var i = 0; i < tickCount; i += step) { - var tick = realNumberScaleTicks ? realNumberScaleTicks[i] : { - value: categoryScaleExtent[0] + i - }; - var label = labelFormatter(tick, i); - var unrotatedSingleRect = axisLabelModel.getTextRect(label); - var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0); - rect ? rect.union(singleRect) : rect = singleRect; - } - - return rect; - } - - function rotateTextRect(textRect, rotate) { - var rotateRadians = rotate * Math.PI / 180; - var beforeWidth = textRect.width; - var beforeHeight = textRect.height; - var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians)); - var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians)); - var rotatedRect = new BoundingRect(textRect.x, textRect.y, afterWidth, afterHeight); - return rotatedRect; - } - /** - * @param model axisLabelModel or axisTickModel - * @return {number|String} Can be null|'auto'|number|function - */ - - - function getOptionCategoryInterval(model) { - var interval = model.get('interval'); - return interval == null ? 'auto' : interval; - } - /** - * Set `categoryInterval` as 0 implicitly indicates that - * show all labels regardless of overlap. - * @param {Object} axis axisModel.axis - */ - - - function shouldShowAllLabels(axis) { - return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0; - } - - function getDataDimensionsOnAxis(data, axisDim) { - // Remove duplicated dat dimensions caused by `getStackedDimension`. - var dataDimMap = {}; // Currently `mapDimensionsAll` will contain stack result dimension ('__\0ecstackresult'). - // PENDING: is it reasonable? Do we need to remove the original dim from "coord dim" since - // there has been stacked result dim? - - each$4(data.mapDimensionsAll(axisDim), function (dataDim) { - // For example, the extent of the original dimension - // is [0.1, 0.5], the extent of the `stackResultDimension` - // is [7, 9], the final extent should NOT include [0.1, 0.5], - // because there is no graphic corresponding to [0.1, 0.5]. - // See the case in `test/area-stack.html` `main1`, where area line - // stack needs `yAxis` not start from 0. - dataDimMap[getStackedDimension(data, dataDim)] = true; - }); - return keys(dataDimMap); - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - - - var AxisModelCommonMixin = - /** @class */ - function () { - function AxisModelCommonMixin() {} - - AxisModelCommonMixin.prototype.getNeedCrossZero = function () { - var option = this.option; - return !option.scale; - }; - /** - * Should be implemented by each axis model if necessary. - * @return coordinate system model - */ - - - AxisModelCommonMixin.prototype.getCoordSysModel = function () { - return; - }; - - return AxisModelCommonMixin; - }(); - /** - * Create a multi dimension List structure from seriesModel. - */ - - - function createList(seriesModel) { - return createSeriesData(null, seriesModel); - } - - var dataStack = { - isDimensionStacked: isDimensionStacked, - enableDataStack: enableDataStack, - getStackedDimension: getStackedDimension - }; - /** - * Create scale - * @param {Array.} dataExtent - * @param {Object|module:echarts/Model} option If `optoin.type` - * is secified, it can only be `'value'` currently. - */ - - function createScale(dataExtent, option) { - var axisModel = option; - - if (!(option instanceof Model)) { - axisModel = new Model(option); // FIXME - // Currently AxisModelCommonMixin has nothing to do with the - // the requirements of `axisHelper.createScaleByModel`. For - // example the methods `getCategories` and `getOrdinalMeta` - // are required for `'category'` axis, and ecModel is required - // for `'time'` axis. But occasionally echarts-gl happened - // to only use `'value'` axis. - // zrUtil.mixin(axisModel, AxisModelCommonMixin); - } - - var scale = createScaleByModel(axisModel); - scale.setExtent(dataExtent[0], dataExtent[1]); - niceScaleExtent(scale, axisModel); - return scale; - } - /** - * Mixin common methods to axis model, - * - * Include methods - * `getFormattedLabels() => Array.` - * `getCategories() => Array.` - * `getMin(origin: boolean) => number` - * `getMax(origin: boolean) => number` - * `getNeedCrossZero() => boolean` - */ - - - function mixinAxisModelCommonMethods(Model) { - mixin(Model, AxisModelCommonMixin); - } - - function createTextStyle(textStyleModel, opts) { - opts = opts || {}; - return createTextStyle$1(textStyleModel, null, null, opts.state !== 'normal'); - } - - var helper = /*#__PURE__*/Object.freeze({ - __proto__: null, - createDimensions: createDimensions, - createList: createList, - createScale: createScale, - createSymbol: createSymbol, - createTextStyle: createTextStyle, - dataStack: dataStack, - enableHoverEmphasis: enableHoverEmphasis, - getECData: getECData, - getLayoutRect: getLayoutRect, - mixinAxisModelCommonMethods: mixinAxisModelCommonMethods - }); - var extensions = []; - var extensionRegisters = { - registerPreprocessor: registerPreprocessor, - registerProcessor: registerProcessor, - registerPostInit: registerPostInit, - registerPostUpdate: registerPostUpdate, - registerUpdateLifecycle: registerUpdateLifecycle, - registerAction: registerAction, - registerCoordinateSystem: registerCoordinateSystem, - registerLayout: registerLayout, - registerVisual: registerVisual, - registerTransform: registerTransform, - registerLoading: registerLoading, - registerMap: registerMap, - registerImpl: registerImpl, - PRIORITY: PRIORITY, - ComponentModel: ComponentModel, - ComponentView: ComponentView, - SeriesModel: SeriesModel, - ChartView: ChartView, - // TODO Use ComponentModel and SeriesModel instead of Constructor - registerComponentModel: function (ComponentModelClass) { - ComponentModel.registerClass(ComponentModelClass); - }, - registerComponentView: function (ComponentViewClass) { - ComponentView.registerClass(ComponentViewClass); - }, - registerSeriesModel: function (SeriesModelClass) { - SeriesModel.registerClass(SeriesModelClass); - }, - registerChartView: function (ChartViewClass) { - ChartView.registerClass(ChartViewClass); - }, - registerSubTypeDefaulter: function (componentType, defaulter) { - ComponentModel.registerSubTypeDefaulter(componentType, defaulter); - }, - registerPainter: function (painterType, PainterCtor) { - registerPainter(painterType, PainterCtor); - } - }; - - function use(ext) { - if (isArray(ext)) { - // use([ChartLine, ChartBar]); - each$4(ext, function (singleExt) { - use(singleExt); - }); - return; - } - - if (indexOf(extensions, ext) >= 0) { - return; - } - - extensions.push(ext); - - if (isFunction(ext)) { - ext = { - install: ext - }; - } - - ext.install(extensionRegisters); - } - - var EPSILON = 1e-8; - - function isAroundEqual(a, b) { - return Math.abs(a - b) < EPSILON; - } - - function contain(points, x, y) { - var w = 0; - var p = points[0]; - - if (!p) { - return false; - } - - for (var i = 1; i < points.length; i++) { - var p2 = points[i]; - w += windingLine(p[0], p[1], p2[0], p2[1], x, y); - p = p2; - } - - var p0 = points[0]; - - if (!isAroundEqual(p[0], p0[0]) || !isAroundEqual(p[1], p0[1])) { - w += windingLine(p[0], p[1], p0[0], p0[1], x, y); - } - - return w !== 0; - } - - var TMP_TRANSFORM = []; - - function transformPoints(points, transform) { - for (var p = 0; p < points.length; p++) { - applyTransform$1(points[p], points[p], transform); - } - } - - function updateBBoxFromPoints(points, min, max, projection) { - for (var i = 0; i < points.length; i++) { - var p = points[i]; - - if (projection) { - // projection may return null point. - p = projection.project(p); - } - - if (p && isFinite(p[0]) && isFinite(p[1])) { - min$1(min, min, p); - max$1(max, max, p); - } - } - } - - function centroid(points) { - var signedArea = 0; - var cx = 0; - var cy = 0; - var len = points.length; - var x0 = points[len - 1][0]; - var y0 = points[len - 1][1]; // Polygon should been closed. - - for (var i = 0; i < len; i++) { - var x1 = points[i][0]; - var y1 = points[i][1]; - var a = x0 * y1 - x1 * y0; - signedArea += a; - cx += (x0 + x1) * a; - cy += (y0 + y1) * a; - x0 = x1; - y0 = y1; - } - - return signedArea ? [cx / signedArea / 3, cy / signedArea / 3, signedArea] : [points[0][0] || 0, points[0][1] || 0]; - } - - var Region = - /** @class */ - function () { - function Region(name) { - this.name = name; - } - - Region.prototype.setCenter = function (center) { - this._center = center; - }; - /** - * Get center point in data unit. That is, - * for GeoJSONRegion, the unit is lat/lng, - * for GeoSVGRegion, the unit is SVG local coord. - */ - - - Region.prototype.getCenter = function () { - var center = this._center; - - if (!center) { - // In most cases there are no need to calculate this center. - // So calculate only when called. - center = this._center = this.calcCenter(); - } - - return center; - }; - - return Region; - }(); - - var GeoJSONPolygonGeometry = - /** @class */ - function () { - function GeoJSONPolygonGeometry(exterior, interiors) { - this.type = 'polygon'; - this.exterior = exterior; - this.interiors = interiors; - } - - return GeoJSONPolygonGeometry; - }(); - - var GeoJSONLineStringGeometry = - /** @class */ - function () { - function GeoJSONLineStringGeometry(points) { - this.type = 'linestring'; - this.points = points; - } - - return GeoJSONLineStringGeometry; - }(); - - var GeoJSONRegion = - /** @class */ - function (_super) { - __extends(GeoJSONRegion, _super); - - function GeoJSONRegion(name, geometries, cp) { - var _this = _super.call(this, name) || this; - - _this.type = 'geoJSON'; - _this.geometries = geometries; - _this._center = cp && [cp[0], cp[1]]; - return _this; - } - - GeoJSONRegion.prototype.calcCenter = function () { - var geometries = this.geometries; - var largestGeo; - var largestGeoSize = 0; - - for (var i = 0; i < geometries.length; i++) { - var geo = geometries[i]; - var exterior = geo.exterior; // Simple trick to use points count instead of polygon area as region size. - // Ignore linestring - - var size = exterior && exterior.length; - - if (size > largestGeoSize) { - largestGeo = geo; - largestGeoSize = size; - } - } - - if (largestGeo) { - return centroid(largestGeo.exterior); - } // from bounding rect by default. - - - var rect = this.getBoundingRect(); - return [rect.x + rect.width / 2, rect.y + rect.height / 2]; - }; - - GeoJSONRegion.prototype.getBoundingRect = function (projection) { - var rect = this._rect; // Always recalculate if using projection. - - if (rect && !projection) { - return rect; - } - - var min = [Infinity, Infinity]; - var max = [-Infinity, -Infinity]; - var geometries = this.geometries; - each$4(geometries, function (geo) { - if (geo.type === 'polygon') { - // Doesn't consider hole - updateBBoxFromPoints(geo.exterior, min, max, projection); - } else { - each$4(geo.points, function (points) { - updateBBoxFromPoints(points, min, max, projection); - }); - } - }); // Normalie invalid bounding. - - if (!(isFinite(min[0]) && isFinite(min[1]) && isFinite(max[0]) && isFinite(max[1]))) { - min[0] = min[1] = max[0] = max[1] = 0; - } - - rect = new BoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); - - if (!projection) { - this._rect = rect; - } - - return rect; - }; - - GeoJSONRegion.prototype.contain = function (coord) { - var rect = this.getBoundingRect(); - var geometries = this.geometries; - - if (!rect.contain(coord[0], coord[1])) { - return false; - } - - loopGeo: for (var i = 0, len = geometries.length; i < len; i++) { - var geo = geometries[i]; // Only support polygon. - - if (geo.type !== 'polygon') { - continue; - } - - var exterior = geo.exterior; - var interiors = geo.interiors; - - if (contain(exterior, coord[0], coord[1])) { - // Not in the region if point is in the hole. - for (var k = 0; k < (interiors ? interiors.length : 0); k++) { - if (contain(interiors[k], coord[0], coord[1])) { - continue loopGeo; - } - } - - return true; - } - } - - return false; - }; - /** - * Transform the raw coords to target bounding. - * @param x - * @param y - * @param width - * @param height - */ - - - GeoJSONRegion.prototype.transformTo = function (x, y, width, height) { - var rect = this.getBoundingRect(); - var aspect = rect.width / rect.height; - - if (!width) { - width = aspect * height; - } else if (!height) { - height = width / aspect; - } - - var target = new BoundingRect(x, y, width, height); - var transform = rect.calculateTransform(target); - var geometries = this.geometries; - - for (var i = 0; i < geometries.length; i++) { - var geo = geometries[i]; - - if (geo.type === 'polygon') { - transformPoints(geo.exterior, transform); - each$4(geo.interiors, function (interior) { - transformPoints(interior, transform); - }); - } else { - each$4(geo.points, function (points) { - transformPoints(points, transform); - }); - } - } - - rect = this._rect; - rect.copy(target); // Update center - - this._center = [rect.x + rect.width / 2, rect.y + rect.height / 2]; - }; - - GeoJSONRegion.prototype.cloneShallow = function (name) { - name == null && (name = this.name); - var newRegion = new GeoJSONRegion(name, this.geometries, this._center); - newRegion._rect = this._rect; - newRegion.transformTo = null; // Simply avoid to be called. - - return newRegion; - }; - - return GeoJSONRegion; - }(Region); - /** @class */ - - - (function (_super) { - __extends(GeoSVGRegion, _super); - - function GeoSVGRegion(name, elOnlyForCalculate) { - var _this = _super.call(this, name) || this; - - _this.type = 'geoSVG'; - _this._elOnlyForCalculate = elOnlyForCalculate; - return _this; - } - - GeoSVGRegion.prototype.calcCenter = function () { - var el = this._elOnlyForCalculate; - var rect = el.getBoundingRect(); - var center = [rect.x + rect.width / 2, rect.y + rect.height / 2]; - var mat = identity(TMP_TRANSFORM); - var target = el; - - while (target && !target.isGeoSVGGraphicRoot) { - mul(mat, target.getLocalTransform(), mat); - target = target.parent; - } - - invert(mat, mat); - applyTransform$1(center, center, mat); - return center; - }; - - return GeoSVGRegion; - })(Region); - - function decode(json) { - if (!json.UTF8Encoding) { - return json; - } - - var jsonCompressed = json; - var encodeScale = jsonCompressed.UTF8Scale; - - if (encodeScale == null) { - encodeScale = 1024; - } - - var features = jsonCompressed.features; - each$4(features, function (feature) { - var geometry = feature.geometry; - var encodeOffsets = geometry.encodeOffsets; - var coordinates = geometry.coordinates; // Geometry may be appeded manually in the script after json loaded. - // In this case this geometry is usually not encoded. - - if (!encodeOffsets) { - return; - } - - switch (geometry.type) { - case 'LineString': - geometry.coordinates = decodeRing(coordinates, encodeOffsets, encodeScale); - break; - - case 'Polygon': - decodeRings(coordinates, encodeOffsets, encodeScale); - break; - - case 'MultiLineString': - decodeRings(coordinates, encodeOffsets, encodeScale); - break; - - case 'MultiPolygon': - each$4(coordinates, function (rings, idx) { - return decodeRings(rings, encodeOffsets[idx], encodeScale); - }); - } - }); // Has been decoded - - jsonCompressed.UTF8Encoding = false; - return jsonCompressed; - } - - function decodeRings(rings, encodeOffsets, encodeScale) { - for (var c = 0; c < rings.length; c++) { - rings[c] = decodeRing(rings[c], encodeOffsets[c], encodeScale); - } - } - - function decodeRing(coordinate, encodeOffsets, encodeScale) { - var result = []; - var prevX = encodeOffsets[0]; - var prevY = encodeOffsets[1]; - - for (var i = 0; i < coordinate.length; i += 2) { - var x = coordinate.charCodeAt(i) - 64; - var y = coordinate.charCodeAt(i + 1) - 64; // ZigZag decoding - - x = x >> 1 ^ -(x & 1); - y = y >> 1 ^ -(y & 1); // Delta deocding - - x += prevX; - y += prevY; - prevX = x; - prevY = y; // Dequantize - - result.push([x / encodeScale, y / encodeScale]); - } - - return result; - } - - function parseGeoJSON(geoJson, nameProperty) { - geoJson = decode(geoJson); - return map$1(filter(geoJson.features, function (featureObj) { - // Output of mapshaper may have geometry null - return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0; - }), function (featureObj) { - var properties = featureObj.properties; - var geo = featureObj.geometry; - var geometries = []; - - switch (geo.type) { - case 'Polygon': - var coordinates = geo.coordinates; // According to the GeoJSON specification. - // First must be exterior, and the rest are all interior(holes). - - geometries.push(new GeoJSONPolygonGeometry(coordinates[0], coordinates.slice(1))); - break; - - case 'MultiPolygon': - each$4(geo.coordinates, function (item) { - if (item[0]) { - geometries.push(new GeoJSONPolygonGeometry(item[0], item.slice(1))); - } - }); - break; - - case 'LineString': - geometries.push(new GeoJSONLineStringGeometry([geo.coordinates])); - break; - - case 'MultiLineString': - geometries.push(new GeoJSONLineStringGeometry(geo.coordinates)); - } - - var region = new GeoJSONRegion(properties[nameProperty || 'name'], geometries, properties.cp); - region.properties = properties; - return region; - }); - } - - var number = /*#__PURE__*/Object.freeze({ - __proto__: null, - MAX_SAFE_INTEGER: MAX_SAFE_INTEGER, - asc: asc, - getPercentWithPrecision: getPercentWithPrecision, - getPixelPrecision: getPixelPrecision, - getPrecision: getPrecision, - getPrecisionSafe: getPrecisionSafe, - isNumeric: isNumeric, - isRadianAroundZero: isRadianAroundZero, - linearMap: linearMap, - nice: nice, - numericToNumber: numericToNumber, - parseDate: parseDate, - quantile: quantile, - quantity: quantity, - quantityExponent: quantityExponent, - reformIntervals: reformIntervals, - remRadian: remRadian, - round: round$2 - }); - var time = /*#__PURE__*/Object.freeze({ - __proto__: null, - format: format$1, - parse: parseDate - }); - var graphic = /*#__PURE__*/Object.freeze({ - __proto__: null, - Arc: Arc, - BezierCurve: BezierCurve, - BoundingRect: BoundingRect, - Circle: Circle, - CompoundPath: CompoundPath, - Ellipse: Ellipse, - Group: Group$2, - Image: ZRImage, - IncrementalDisplayable: IncrementalDisplayable, - Line: Line, - LinearGradient: LinearGradient, - Polygon: Polygon, - Polyline: Polyline, - RadialGradient: RadialGradient, - Rect: Rect, - Ring: Ring, - Sector: Sector, - Text: ZRText, - clipPointsByRect: clipPointsByRect, - clipRectByRect: clipRectByRect, - createIcon: createIcon, - extendPath: extendPath, - extendShape: extendShape, - getShapeClass: getShapeClass, - getTransform: getTransform, - initProps: initProps, - makeImage: makeImage, - makePath: makePath, - mergePath: mergePath, - registerShape: registerShape, - resizePath: resizePath, - updateProps: updateProps$1 - }); - var format = /*#__PURE__*/Object.freeze({ - __proto__: null, - addCommas: addCommas, - capitalFirst: capitalFirst, - encodeHTML: encodeHTML, - formatTime: formatTime, - formatTpl: formatTpl, - getTextRect: getTextRect, - getTooltipMarker: getTooltipMarker, - normalizeCssArray: normalizeCssArray, - toCamelCase: toCamelCase, - truncateText: truncateText - }); - var util = /*#__PURE__*/Object.freeze({ - __proto__: null, - bind: bind$1, - clone: clone$3, - curry: curry$1, - defaults: defaults, - each: each$4, - extend: extend, - filter: filter, - indexOf: indexOf, - inherits: inherits, - isArray: isArray, - isFunction: isFunction, - isObject: isObject$2, - isString: isString, - map: map$1, - merge: merge, - reduce: reduce - }); - var inner$4 = makeInner(); - - function createAxisLabels(axis) { - // Only ordinal scale support tick interval - return axis.type === 'category' ? makeCategoryLabels(axis) : makeRealNumberLabels(axis); - } - /** - * @param {module:echats/coord/Axis} axis - * @param {module:echarts/model/Model} tickModel For example, can be axisTick, splitLine, splitArea. - * @return {Object} { - * ticks: Array. - * tickCategoryInterval: number - * } - */ - - - function createAxisTicks(axis, tickModel) { - // Only ordinal scale support tick interval - return axis.type === 'category' ? makeCategoryTicks(axis, tickModel) : { - ticks: map$1(axis.scale.getTicks(), function (tick) { - return tick.value; - }) - }; - } - - function makeCategoryLabels(axis) { - var labelModel = axis.getLabelModel(); - var result = makeCategoryLabelsActually(axis, labelModel); - return !labelModel.get('show') || axis.scale.isBlank() ? { - labels: [], - labelCategoryInterval: result.labelCategoryInterval - } : result; - } - - function makeCategoryLabelsActually(axis, labelModel) { - var labelsCache = getListCache(axis, 'labels'); - var optionLabelInterval = getOptionCategoryInterval(labelModel); - var result = listCacheGet(labelsCache, optionLabelInterval); - - if (result) { - return result; - } - - var labels; - var numericLabelInterval; - - if (isFunction(optionLabelInterval)) { - labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval); - } else { - numericLabelInterval = optionLabelInterval === 'auto' ? makeAutoCategoryInterval(axis) : optionLabelInterval; - labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval); - } // Cache to avoid calling interval function repeatedly. - - - return listCacheSet(labelsCache, optionLabelInterval, { - labels: labels, - labelCategoryInterval: numericLabelInterval - }); - } - - function makeCategoryTicks(axis, tickModel) { - var ticksCache = getListCache(axis, 'ticks'); - var optionTickInterval = getOptionCategoryInterval(tickModel); - var result = listCacheGet(ticksCache, optionTickInterval); - - if (result) { - return result; - } - - var ticks; - var tickCategoryInterval; // Optimize for the case that large category data and no label displayed, - // we should not return all ticks. - - if (!tickModel.get('show') || axis.scale.isBlank()) { - ticks = []; - } - - if (isFunction(optionTickInterval)) { - ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true); - } // Always use label interval by default despite label show. Consider this - // scenario, Use multiple grid with the xAxis sync, and only one xAxis shows - // labels. `splitLine` and `axisTick` should be consistent in this case. - else if (optionTickInterval === 'auto') { - var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel()); - tickCategoryInterval = labelsResult.labelCategoryInterval; - ticks = map$1(labelsResult.labels, function (labelItem) { - return labelItem.tickValue; - }); - } else { - tickCategoryInterval = optionTickInterval; - ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true); - } // Cache to avoid calling interval function repeatedly. - - - return listCacheSet(ticksCache, optionTickInterval, { - ticks: ticks, - tickCategoryInterval: tickCategoryInterval - }); - } - - function makeRealNumberLabels(axis) { - var ticks = axis.scale.getTicks(); - var labelFormatter = makeLabelFormatter(axis); - return { - labels: map$1(ticks, function (tick, idx) { - return { - level: tick.level, - formattedLabel: labelFormatter(tick, idx), - rawLabel: axis.scale.getLabel(tick), - tickValue: tick.value - }; - }) - }; - } - - function getListCache(axis, prop) { - // Because key can be a function, and cache size always is small, we use array cache. - return inner$4(axis)[prop] || (inner$4(axis)[prop] = []); - } - - function listCacheGet(cache, key) { - for (var i = 0; i < cache.length; i++) { - if (cache[i].key === key) { - return cache[i].value; - } - } - } - - function listCacheSet(cache, key, value) { - cache.push({ - key: key, - value: value - }); - return value; - } - - function makeAutoCategoryInterval(axis) { - var result = inner$4(axis).autoInterval; - return result != null ? result : inner$4(axis).autoInterval = axis.calculateCategoryInterval(); - } - /** - * Calculate interval for category axis ticks and labels. - * To get precise result, at least one of `getRotate` and `isHorizontal` - * should be implemented in axis. - */ - - - function calculateCategoryInterval(axis) { - var params = fetchAutoCategoryIntervalCalculationParams(axis); - var labelFormatter = makeLabelFormatter(axis); - var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI; - var ordinalScale = axis.scale; - var ordinalExtent = ordinalScale.getExtent(); // Providing this method is for optimization: - // avoid generating a long array by `getTicks` - // in large category data case. - - var tickCount = ordinalScale.count(); - - if (ordinalExtent[1] - ordinalExtent[0] < 1) { - return 0; - } - - var step = 1; // Simple optimization. Empirical value: tick count should less than 40. - - if (tickCount > 40) { - step = Math.max(1, Math.floor(tickCount / 40)); - } - - var tickValue = ordinalExtent[0]; - var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); - var unitW = Math.abs(unitSpan * Math.cos(rotation)); - var unitH = Math.abs(unitSpan * Math.sin(rotation)); - var maxW = 0; - var maxH = 0; // Caution: Performance sensitive for large category data. - // Consider dataZoom, we should make appropriate step to avoid O(n) loop. - - for (; tickValue <= ordinalExtent[1]; tickValue += step) { - var width = 0; - var height = 0; // Not precise, do not consider align and vertical align - // and each distance from axis line yet. - - var rect = getBoundingRect(labelFormatter({ - value: tickValue - }), params.font, 'center', 'top'); // Magic number - - width = rect.width * 1.3; - height = rect.height * 1.3; // Min size, void long loop. - - maxW = Math.max(maxW, width, 7); - maxH = Math.max(maxH, height, 7); - } - - var dw = maxW / unitW; - var dh = maxH / unitH; // 0/0 is NaN, 1/0 is Infinity. - - isNaN(dw) && (dw = Infinity); - isNaN(dh) && (dh = Infinity); - var interval = Math.max(0, Math.floor(Math.min(dw, dh))); - var cache = inner$4(axis.model); - var axisExtent = axis.getExtent(); - var lastAutoInterval = cache.lastAutoInterval; - var lastTickCount = cache.lastTickCount; // Use cache to keep interval stable while moving zoom window, - // otherwise the calculated interval might jitter when the zoom - // window size is close to the interval-changing size. - // For example, if all of the axis labels are `a, b, c, d, e, f, g`. - // The jitter will cause that sometimes the displayed labels are - // `a, d, g` (interval: 2) sometimes `a, c, e`(interval: 1). - - if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 // Always choose the bigger one, otherwise the critical - // point is not the same when zooming in or zooming out. - && lastAutoInterval > interval // If the axis change is caused by chart resize, the cache should not - // be used. Otherwise some hidden labels might not be shown again. - && cache.axisExtent0 === axisExtent[0] && cache.axisExtent1 === axisExtent[1]) { - interval = lastAutoInterval; - } // Only update cache if cache not used, otherwise the - // changing of interval is too insensitive. - else { - cache.lastTickCount = tickCount; - cache.lastAutoInterval = interval; - cache.axisExtent0 = axisExtent[0]; - cache.axisExtent1 = axisExtent[1]; - } - - return interval; - } - - function fetchAutoCategoryIntervalCalculationParams(axis) { - var labelModel = axis.getLabelModel(); - return { - axisRotate: axis.getRotate ? axis.getRotate() : axis.isHorizontal && !axis.isHorizontal() ? 90 : 0, - labelRotate: labelModel.get('rotate') || 0, - font: labelModel.getFont() - }; - } - - function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) { - var labelFormatter = makeLabelFormatter(axis); - var ordinalScale = axis.scale; - var ordinalExtent = ordinalScale.getExtent(); - var labelModel = axis.getLabelModel(); - var result = []; // TODO: axisType: ordinalTime, pick the tick from each month/day/year/... - - var step = Math.max((categoryInterval || 0) + 1, 1); - var startTick = ordinalExtent[0]; - var tickCount = ordinalScale.count(); // Calculate start tick based on zero if possible to keep label consistent - // while zooming and moving while interval > 0. Otherwise the selection - // of displayable ticks and symbols probably keep changing. - // 3 is empirical value. - - if (startTick !== 0 && step > 1 && tickCount / step > 2) { - startTick = Math.round(Math.ceil(startTick / step) * step); - } // (1) Only add min max label here but leave overlap checking - // to render stage, which also ensure the returned list - // suitable for splitLine and splitArea rendering. - // (2) Scales except category always contain min max label so - // do not need to perform this process. - - - var showAllLabel = shouldShowAllLabels(axis); - var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel; - var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel; - - if (includeMinLabel && startTick !== ordinalExtent[0]) { - addItem(ordinalExtent[0]); - } // Optimize: avoid generating large array by `ordinalScale.getTicks()`. - - - var tickValue = startTick; - - for (; tickValue <= ordinalExtent[1]; tickValue += step) { - addItem(tickValue); - } - - if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) { - addItem(ordinalExtent[1]); - } - - function addItem(tickValue) { - var tickObj = { - value: tickValue - }; - result.push(onlyTick ? tickValue : { - formattedLabel: labelFormatter(tickObj), - rawLabel: ordinalScale.getLabel(tickObj), - tickValue: tickValue - }); - } - - return result; - } - - function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) { - var ordinalScale = axis.scale; - var labelFormatter = makeLabelFormatter(axis); - var result = []; - each$4(ordinalScale.getTicks(), function (tick) { - var rawLabel = ordinalScale.getLabel(tick); - var tickValue = tick.value; - - if (categoryInterval(tick.value, rawLabel)) { - result.push(onlyTick ? tickValue : { - formattedLabel: labelFormatter(tick), - rawLabel: rawLabel, - tickValue: tickValue - }); - } - }); - return result; - } - - var NORMALIZED_EXTENT = [0, 1]; - /** - * Base class of Axis. - */ - - var Axis = - /** @class */ - function () { - function Axis(dim, scale, extent) { - this.onBand = false; - this.inverse = false; - this.dim = dim; - this.scale = scale; - this._extent = extent || [0, 0]; - } - /** - * If axis extent contain given coord - */ - - - Axis.prototype.contain = function (coord) { - var extent = this._extent; - var min = Math.min(extent[0], extent[1]); - var max = Math.max(extent[0], extent[1]); - return coord >= min && coord <= max; - }; - /** - * If axis extent contain given data - */ - - - Axis.prototype.containData = function (data) { - return this.scale.contain(data); - }; - /** - * Get coord extent. - */ - - - Axis.prototype.getExtent = function () { - return this._extent.slice(); - }; - /** - * Get precision used for formatting - */ - - - Axis.prototype.getPixelPrecision = function (dataExtent) { - return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent); - }; - /** - * Set coord extent - */ - - - Axis.prototype.setExtent = function (start, end) { - var extent = this._extent; - extent[0] = start; - extent[1] = end; - }; - /** - * Convert data to coord. Data is the rank if it has an ordinal scale - */ - - - Axis.prototype.dataToCoord = function (data, clamp) { - var extent = this._extent; - var scale = this.scale; - data = scale.normalize(data); - - if (this.onBand && scale.type === 'ordinal') { - extent = extent.slice(); - fixExtentWithBands(extent, scale.count()); - } - - return linearMap(data, NORMALIZED_EXTENT, extent, clamp); - }; - /** - * Convert coord to data. Data is the rank if it has an ordinal scale - */ - - - Axis.prototype.coordToData = function (coord, clamp) { - var extent = this._extent; - var scale = this.scale; - - if (this.onBand && scale.type === 'ordinal') { - extent = extent.slice(); - fixExtentWithBands(extent, scale.count()); - } - - var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp); - return this.scale.scale(t); - }; - /** - * Convert pixel point to data in axis - */ - - - Axis.prototype.pointToData = function (point, clamp) { - // Should be implemented in derived class if necessary. - return; - }; - /** - * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`, - * `axis.getTicksCoords` considers `onBand`, which is used by - * `boundaryGap:true` of category axis and splitLine and splitArea. - * @param opt.tickModel default: axis.model.getModel('axisTick') - * @param opt.clamp If `true`, the first and the last - * tick must be at the axis end points. Otherwise, clip ticks - * that outside the axis extent. - */ - - - Axis.prototype.getTicksCoords = function (opt) { - opt = opt || {}; - var tickModel = opt.tickModel || this.getTickModel(); - var result = createAxisTicks(this, tickModel); - var ticks = result.ticks; - var ticksCoords = map$1(ticks, function (tickVal) { - return { - coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawOrdinalNumber(tickVal) : tickVal), - tickValue: tickVal - }; - }, this); - var alignWithLabel = tickModel.get('alignWithLabel'); - fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp); - return ticksCoords; - }; - - Axis.prototype.getMinorTicksCoords = function () { - if (this.scale.type === 'ordinal') { - // Category axis doesn't support minor ticks - return []; - } - - var minorTickModel = this.model.getModel('minorTick'); - var splitNumber = minorTickModel.get('splitNumber'); // Protection. - - if (!(splitNumber > 0 && splitNumber < 100)) { - splitNumber = 5; - } - - var minorTicks = this.scale.getMinorTicks(splitNumber); - var minorTicksCoords = map$1(minorTicks, function (minorTicksGroup) { - return map$1(minorTicksGroup, function (minorTick) { - return { - coord: this.dataToCoord(minorTick), - tickValue: minorTick - }; - }, this); - }, this); - return minorTicksCoords; - }; - - Axis.prototype.getViewLabels = function () { - return createAxisLabels(this).labels; - }; - - Axis.prototype.getLabelModel = function () { - return this.model.getModel('axisLabel'); - }; - /** - * Notice here we only get the default tick model. For splitLine - * or splitArea, we should pass the splitLineModel or splitAreaModel - * manually when calling `getTicksCoords`. - * In GL, this method may be overridden to: - * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));` - */ - - - Axis.prototype.getTickModel = function () { - return this.model.getModel('axisTick'); - }; - /** - * Get width of band - */ - - - Axis.prototype.getBandWidth = function () { - var axisExtent = this._extent; - var dataExtent = this.scale.getExtent(); - var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); // Fix #2728, avoid NaN when only one data. - - len === 0 && (len = 1); - var size = Math.abs(axisExtent[1] - axisExtent[0]); - return Math.abs(size) / len; - }; - /** - * Only be called in category axis. - * Can be overridden, consider other axes like in 3D. - * @return Auto interval for cateogry axis tick and label - */ - - - Axis.prototype.calculateCategoryInterval = function () { - return calculateCategoryInterval(this); - }; - - return Axis; - }(); - - function fixExtentWithBands(extent, nTick) { - var size = extent[1] - extent[0]; - var len = nTick; - var margin = size / len / 2; - extent[0] += margin; - extent[1] -= margin; - } // If axis has labels [1, 2, 3, 4]. Bands on the axis are - // |---1---|---2---|---3---|---4---|. - // So the displayed ticks and splitLine/splitArea should between - // each data item, otherwise cause misleading (e.g., split tow bars - // of a single data item when there are two bar series). - // Also consider if tickCategoryInterval > 0 and onBand, ticks and - // splitLine/spliteArea should layout appropriately corresponding - // to displayed labels. (So we should not use `getBandWidth` in this - // case). - - - function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) { - var ticksLen = ticksCoords.length; - - if (!axis.onBand || alignWithLabel || !ticksLen) { - return; - } - - var axisExtent = axis.getExtent(); - var last; - var diffSize; - - if (ticksLen === 1) { - ticksCoords[0].coord = axisExtent[0]; - last = ticksCoords[1] = { - coord: axisExtent[1] - }; - } else { - var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue; - var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen; - each$4(ticksCoords, function (ticksItem) { - ticksItem.coord -= shift_1 / 2; - }); - var dataExtent = axis.scale.getExtent(); - diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue; - last = { - coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize - }; - ticksCoords.push(last); - } - - var inverse = axisExtent[0] > axisExtent[1]; // Handling clamp. - - if (littleThan(ticksCoords[0].coord, axisExtent[0])) { - clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift(); - } - - if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) { - ticksCoords.unshift({ - coord: axisExtent[0] - }); - } - - if (littleThan(axisExtent[1], last.coord)) { - clamp ? last.coord = axisExtent[1] : ticksCoords.pop(); - } - - if (clamp && littleThan(last.coord, axisExtent[1])) { - ticksCoords.push({ - coord: axisExtent[1] - }); - } - - function littleThan(a, b) { - // Avoid rounding error cause calculated tick coord different with extent. - // It may cause an extra unnecessary tick added. - a = round$2(a); - b = round$2(b); - return inverse ? a > b : a < b; - } - } // --------------------- Deprecated Extension Methods --------------------- - // Should use `ComponentModel.extend` or `class XXXX extend ComponentModel` to create class. - // Then use `registerComponentModel` in `install` parameter when `use` this extension. For example: - // class Bar3DModel extends ComponentModel {} - // export function install(registers) { registers.registerComponentModel(Bar3DModel); } - // echarts.use(install); - - - function extendComponentModel(proto) { - var Model = ComponentModel.extend(proto); - ComponentModel.registerClass(Model); - return Model; - } - - function extendComponentView(proto) { - var View = ComponentView.extend(proto); - ComponentView.registerClass(View); - return View; - } - - function extendSeriesModel(proto) { - var Model = SeriesModel.extend(proto); - SeriesModel.registerClass(Model); - return Model; - } - - function extendChartView(proto) { - var View = ChartView.extend(proto); - ChartView.registerClass(View); - return View; - } - - var PI2$2 = Math.PI * 2; - var CMD = PathProxy.CMD; - var DEFAULT_SEARCH_SPACE = ['top', 'right', 'bottom', 'left']; - - function getCandidateAnchor(pos, distance, rect, outPt, outDir) { - var width = rect.width; - var height = rect.height; - - switch (pos) { - case 'top': - outPt.set(rect.x + width / 2, rect.y - distance); - outDir.set(0, -1); - break; - - case 'bottom': - outPt.set(rect.x + width / 2, rect.y + height + distance); - outDir.set(0, 1); - break; - - case 'left': - outPt.set(rect.x - distance, rect.y + height / 2); - outDir.set(-1, 0); - break; - - case 'right': - outPt.set(rect.x + width + distance, rect.y + height / 2); - outDir.set(1, 0); - break; - } - } - - function projectPointToArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y, out) { - x -= cx; - y -= cy; - var d = Math.sqrt(x * x + y * y); - x /= d; - y /= d; // Intersect point. - - var ox = x * r + cx; - var oy = y * r + cy; - - if (Math.abs(startAngle - endAngle) % PI2$2 < 1e-4) { - // Is a circle - out[0] = ox; - out[1] = oy; - return d - r; - } - - if (anticlockwise) { - var tmp = startAngle; - startAngle = normalizeRadian(endAngle); - endAngle = normalizeRadian(tmp); - } else { - startAngle = normalizeRadian(startAngle); - endAngle = normalizeRadian(endAngle); - } - - if (startAngle > endAngle) { - endAngle += PI2$2; - } - - var angle = Math.atan2(y, x); - - if (angle < 0) { - angle += PI2$2; - } - - if (angle >= startAngle && angle <= endAngle || angle + PI2$2 >= startAngle && angle + PI2$2 <= endAngle) { - // Project point is on the arc. - out[0] = ox; - out[1] = oy; - return d - r; - } - - var x1 = r * Math.cos(startAngle) + cx; - var y1 = r * Math.sin(startAngle) + cy; - var x2 = r * Math.cos(endAngle) + cx; - var y2 = r * Math.sin(endAngle) + cy; - var d1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y); - var d2 = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y); - - if (d1 < d2) { - out[0] = x1; - out[1] = y1; - return Math.sqrt(d1); - } else { - out[0] = x2; - out[1] = y2; - return Math.sqrt(d2); - } - } - - function projectPointToLine(x1, y1, x2, y2, x, y, out, limitToEnds) { - var dx = x - x1; - var dy = y - y1; - var dx1 = x2 - x1; - var dy1 = y2 - y1; - var lineLen = Math.sqrt(dx1 * dx1 + dy1 * dy1); - dx1 /= lineLen; - dy1 /= lineLen; // dot product - - var projectedLen = dx * dx1 + dy * dy1; - var t = projectedLen / lineLen; - - if (limitToEnds) { - t = Math.min(Math.max(t, 0), 1); - } - - t *= lineLen; - var ox = out[0] = x1 + t * dx1; - var oy = out[1] = y1 + t * dy1; - return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); - } - - function projectPointToRect(x1, y1, width, height, x, y, out) { - if (width < 0) { - x1 = x1 + width; - width = -width; - } - - if (height < 0) { - y1 = y1 + height; - height = -height; - } - - var x2 = x1 + width; - var y2 = y1 + height; - var ox = out[0] = Math.min(Math.max(x, x1), x2); - var oy = out[1] = Math.min(Math.max(y, y1), y2); - return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); - } - - var tmpPt = []; - - function nearestPointOnRect(pt, rect, out) { - var dist = projectPointToRect(rect.x, rect.y, rect.width, rect.height, pt.x, pt.y, tmpPt); - out.set(tmpPt[0], tmpPt[1]); - return dist; - } - /** - * Calculate min distance corresponding point. - * This method won't evaluate if point is in the path. - */ - - - function nearestPointOnPath(pt, path, out) { - var xi = 0; - var yi = 0; - var x0 = 0; - var y0 = 0; - var x1; - var y1; - var minDist = Infinity; - var data = path.data; - var x = pt.x; - var y = pt.y; - - for (var i = 0; i < data.length;) { - var cmd = data[i++]; - - if (i === 1) { - xi = data[i]; - yi = data[i + 1]; - x0 = xi; - y0 = yi; - } - - var d = minDist; - - switch (cmd) { - case CMD.M: - // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点 - // 在 closePath 的时候使用 - x0 = data[i++]; - y0 = data[i++]; - xi = x0; - yi = y0; - break; - - case CMD.L: - d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD.C: - d = cubicProjectPoint(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD.Q: - d = quadraticProjectPoint(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); - xi = data[i++]; - yi = data[i++]; - break; - - case CMD.A: - // TODO Arc 判断的开销比较大 - var cx = data[i++]; - var cy = data[i++]; - var rx = data[i++]; - var ry = data[i++]; - var theta = data[i++]; - var dTheta = data[i++]; // TODO Arc 旋转 - - i += 1; - var anticlockwise = !!(1 - data[i++]); - x1 = Math.cos(theta) * rx + cx; - y1 = Math.sin(theta) * ry + cy; // 不是直接使用 arc 命令 - - if (i <= 1) { - // 第一个命令起点还未定义 - x0 = x1; - y0 = y1; - } // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放 - - - var _x = (x - cx) * ry / rx + cx; - - d = projectPointToArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y, tmpPt); - xi = Math.cos(theta + dTheta) * rx + cx; - yi = Math.sin(theta + dTheta) * ry + cy; - break; - - case CMD.R: - x0 = xi = data[i++]; - y0 = yi = data[i++]; - var width = data[i++]; - var height = data[i++]; - d = projectPointToRect(x0, y0, width, height, x, y, tmpPt); - break; - - case CMD.Z: - d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt, true); - xi = x0; - yi = y0; - break; - } - - if (d < minDist) { - minDist = d; - out.set(tmpPt[0], tmpPt[1]); - } - } - - return minDist; - } // Temporal variable for intermediate usage. - - - var pt0 = new Point(); - var pt1 = new Point(); - var pt2 = new Point(); - var dir = new Point(); - var dir2 = new Point(); - /** - * Calculate a proper guide line based on the label position and graphic element definition - * @param label - * @param labelRect - * @param target - * @param targetRect - */ - - function updateLabelLinePoints(target, labelLineModel) { - if (!target) { - return; - } - - var labelLine = target.getTextGuideLine(); - var label = target.getTextContent(); // Needs to create text guide in each charts. - - if (!(label && labelLine)) { - return; - } - - var labelGuideConfig = target.textGuideLineConfig || {}; - var points = [[0, 0], [0, 0], [0, 0]]; - var searchSpace = labelGuideConfig.candidates || DEFAULT_SEARCH_SPACE; - var labelRect = label.getBoundingRect().clone(); - labelRect.applyTransform(label.getComputedTransform()); - var minDist = Infinity; - var anchorPoint = labelGuideConfig.anchor; - var targetTransform = target.getComputedTransform(); - var targetInversedTransform = targetTransform && invert([], targetTransform); - var len = labelLineModel.get('length2') || 0; - - if (anchorPoint) { - pt2.copy(anchorPoint); - } - - for (var i = 0; i < searchSpace.length; i++) { - var candidate = searchSpace[i]; - getCandidateAnchor(candidate, 0, labelRect, pt0, dir); - Point.scaleAndAdd(pt1, pt0, dir, len); // Transform to target coord space. - - pt1.transform(targetInversedTransform); // Note: getBoundingRect will ensure the `path` being created. - - var boundingRect = target.getBoundingRect(); - var dist = anchorPoint ? anchorPoint.distance(pt1) : target instanceof Path ? nearestPointOnPath(pt1, target.path, pt2) : nearestPointOnRect(pt1, boundingRect, pt2); // TODO pt2 is in the path - - if (dist < minDist) { - minDist = dist; // Transform back to global space. - - pt1.transform(targetTransform); - pt2.transform(targetTransform); - pt2.toArray(points[0]); - pt1.toArray(points[1]); - pt0.toArray(points[2]); - } - } - - limitTurnAngle(points, labelLineModel.get('minTurnAngle')); - labelLine.setShape({ - points: points - }); - } // Temporal variable for the limitTurnAngle function - - - var tmpArr = []; - var tmpProjPoint = new Point(); - /** - * Reduce the line segment attached to the label to limit the turn angle between two segments. - * @param linePoints - * @param minTurnAngle Radian of minimum turn angle. 0 - 180 - */ - - function limitTurnAngle(linePoints, minTurnAngle) { - if (!(minTurnAngle <= 180 && minTurnAngle > 0)) { - return; - } - - minTurnAngle = minTurnAngle / 180 * Math.PI; // The line points can be - // /pt1----pt2 (label) - // / - // pt0/ - - pt0.fromArray(linePoints[0]); - pt1.fromArray(linePoints[1]); - pt2.fromArray(linePoints[2]); - Point.sub(dir, pt0, pt1); - Point.sub(dir2, pt2, pt1); - var len1 = dir.len(); - var len2 = dir2.len(); - - if (len1 < 1e-3 || len2 < 1e-3) { - return; - } - - dir.scale(1 / len1); - dir2.scale(1 / len2); - var angleCos = dir.dot(dir2); - var minTurnAngleCos = Math.cos(minTurnAngle); - - if (minTurnAngleCos < angleCos) { - // Smaller than minTurnAngle - // Calculate project point of pt0 on pt1-pt2 - var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); - tmpProjPoint.fromArray(tmpArr); // Calculate new projected length with limited minTurnAngle and get the new connect point - - tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI - minTurnAngle)); // Limit the new calculated connect point between pt1 and pt2. - - var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); - - if (isNaN(t)) { - return; - } - - if (t < 0) { - Point.copy(tmpProjPoint, pt1); - } else if (t > 1) { - Point.copy(tmpProjPoint, pt2); - } - - tmpProjPoint.toArray(linePoints[1]); - } - } - /** - * Limit the angle of line and the surface - * @param maxSurfaceAngle Radian of minimum turn angle. 0 - 180. 0 is same direction to normal. 180 is opposite - */ - - - function limitSurfaceAngle(linePoints, surfaceNormal, maxSurfaceAngle) { - if (!(maxSurfaceAngle <= 180 && maxSurfaceAngle > 0)) { - return; - } - - maxSurfaceAngle = maxSurfaceAngle / 180 * Math.PI; - pt0.fromArray(linePoints[0]); - pt1.fromArray(linePoints[1]); - pt2.fromArray(linePoints[2]); - Point.sub(dir, pt1, pt0); - Point.sub(dir2, pt2, pt1); - var len1 = dir.len(); - var len2 = dir2.len(); - - if (len1 < 1e-3 || len2 < 1e-3) { - return; - } - - dir.scale(1 / len1); - dir2.scale(1 / len2); - var angleCos = dir.dot(surfaceNormal); - var maxSurfaceAngleCos = Math.cos(maxSurfaceAngle); - - if (angleCos < maxSurfaceAngleCos) { - // Calculate project point of pt0 on pt1-pt2 - var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); - tmpProjPoint.fromArray(tmpArr); - var HALF_PI = Math.PI / 2; - var angle2 = Math.acos(dir2.dot(surfaceNormal)); - var newAngle = HALF_PI + angle2 - maxSurfaceAngle; - - if (newAngle >= HALF_PI) { - // parallel - Point.copy(tmpProjPoint, pt2); - } else { - // Calculate new projected length with limited minTurnAngle and get the new connect point - tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI / 2 - newAngle)); // Limit the new calculated connect point between pt1 and pt2. - - var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); - - if (isNaN(t)) { - return; - } - - if (t < 0) { - Point.copy(tmpProjPoint, pt1); - } else if (t > 1) { - Point.copy(tmpProjPoint, pt2); - } - } - - tmpProjPoint.toArray(linePoints[1]); - } - } - - function setLabelLineState(labelLine, ignore, stateName, stateModel) { - var isNormal = stateName === 'normal'; - var stateObj = isNormal ? labelLine : labelLine.ensureState(stateName); // Make sure display. - - stateObj.ignore = ignore; // Set smooth - - var smooth = stateModel.get('smooth'); - - if (smooth && smooth === true) { - smooth = 0.3; - } - - stateObj.shape = stateObj.shape || {}; - - if (smooth > 0) { - stateObj.shape.smooth = smooth; - } - - var styleObj = stateModel.getModel('lineStyle').getLineStyle(); - isNormal ? labelLine.useStyle(styleObj) : stateObj.style = styleObj; - } - - function buildLabelLinePath(path, shape) { - var smooth = shape.smooth; - var points = shape.points; - - if (!points) { - return; - } - - path.moveTo(points[0][0], points[0][1]); - - if (smooth > 0 && points.length >= 3) { - var len1 = dist$1(points[0], points[1]); - var len2 = dist$1(points[1], points[2]); - - if (!len1 || !len2) { - path.lineTo(points[1][0], points[1][1]); - path.lineTo(points[2][0], points[2][1]); - return; - } - - var moveLen = Math.min(len1, len2) * smooth; - var midPoint0 = lerp$1([], points[1], points[0], moveLen / len1); - var midPoint2 = lerp$1([], points[1], points[2], moveLen / len2); - var midPoint1 = lerp$1([], midPoint0, midPoint2, 0.5); - path.bezierCurveTo(midPoint0[0], midPoint0[1], midPoint0[0], midPoint0[1], midPoint1[0], midPoint1[1]); - path.bezierCurveTo(midPoint2[0], midPoint2[1], midPoint2[0], midPoint2[1], points[2][0], points[2][1]); - } else { - for (var i = 1; i < points.length; i++) { - path.lineTo(points[i][0], points[i][1]); - } - } - } - /** - * Create a label line if necessary and set it's style. - */ - - - function setLabelLineStyle(targetEl, statesModels, defaultStyle) { - var labelLine = targetEl.getTextGuideLine(); - var label = targetEl.getTextContent(); - - if (!label) { - // Not show label line if there is no label. - if (labelLine) { - targetEl.removeTextGuideLine(); - } - - return; - } - - var normalModel = statesModels.normal; - var showNormal = normalModel.get('show'); - var labelIgnoreNormal = label.ignore; - - for (var i = 0; i < DISPLAY_STATES.length; i++) { - var stateName = DISPLAY_STATES[i]; - var stateModel = statesModels[stateName]; - var isNormal = stateName === 'normal'; - - if (stateModel) { - var stateShow = stateModel.get('show'); - var isLabelIgnored = isNormal ? labelIgnoreNormal : retrieve2(label.states[stateName] && label.states[stateName].ignore, labelIgnoreNormal); - - if (isLabelIgnored // Not show when label is not shown in this state. - || !retrieve2(stateShow, showNormal) // Use normal state by default if not set. - ) { - var stateObj = isNormal ? labelLine : labelLine && labelLine.states[stateName]; - - if (stateObj) { - stateObj.ignore = true; - } - - if (!!labelLine) { - setLabelLineState(labelLine, true, stateName, stateModel); - } - - continue; - } // Create labelLine if not exists - - - if (!labelLine) { - labelLine = new Polyline(); - targetEl.setTextGuideLine(labelLine); // Reset state of normal because it's new created. - // NOTE: NORMAL should always been the first! - - if (!isNormal && (labelIgnoreNormal || !showNormal)) { - setLabelLineState(labelLine, true, 'normal', statesModels.normal); - } // Use same state proxy. - - - if (targetEl.stateProxy) { - labelLine.stateProxy = targetEl.stateProxy; - } - } - - setLabelLineState(labelLine, false, stateName, stateModel); - } - } - - if (labelLine) { - defaults(labelLine.style, defaultStyle); // Not fill. - - labelLine.style.fill = null; - var showAbove = normalModel.get('showAbove'); - var labelLineConfig = targetEl.textGuideLineConfig = targetEl.textGuideLineConfig || {}; - labelLineConfig.showAbove = showAbove || false; // Custom the buildPath. - - labelLine.buildPath = buildLabelLinePath; - } - } - - function getLabelLineStatesModels(itemModel, labelLineName) { - labelLineName = labelLineName || 'labelLine'; - var statesModels = { - normal: itemModel.getModel(labelLineName) - }; - - for (var i = 0; i < SPECIAL_STATES.length; i++) { - var stateName = SPECIAL_STATES[i]; - statesModels[stateName] = itemModel.getModel([stateName, labelLineName]); - } - - return statesModels; - } - - function prepareLayoutList(input) { - var list = []; - - for (var i = 0; i < input.length; i++) { - var rawItem = input[i]; - - if (rawItem.defaultAttr.ignore) { - continue; - } - - var label = rawItem.label; - var transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el. - - var localRect = label.getBoundingRect(); - var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5; - var minMargin = label.style.margin || 0; - var globalRect = localRect.clone(); - globalRect.applyTransform(transform); - globalRect.x -= minMargin / 2; - globalRect.y -= minMargin / 2; - globalRect.width += minMargin; - globalRect.height += minMargin; - var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null; - list.push({ - label: label, - labelLine: rawItem.labelLine, - rect: globalRect, - localRect: localRect, - obb: obb, - priority: rawItem.priority, - defaultAttr: rawItem.defaultAttr, - layoutOption: rawItem.computedLayoutOption, - axisAligned: isAxisAligned, - transform: transform - }); - } - - return list; - } - - function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) { - var len = list.length; - - if (len < 2) { - return; - } - - list.sort(function (a, b) { - return a.rect[xyDim] - b.rect[xyDim]; - }); - var lastPos = 0; - var delta; - var adjusted = false; - var totalShifts = 0; - - for (var i = 0; i < len; i++) { - var item = list[i]; - var rect = item.rect; - delta = rect[xyDim] - lastPos; - - if (delta < 0) { - // shiftForward(i, len, -delta); - rect[xyDim] -= delta; - item.label[xyDim] -= delta; - adjusted = true; - } - - var shift = Math.max(-delta, 0); - totalShifts += shift; - lastPos = rect[xyDim] + rect[sizeDim]; - } - - if (totalShifts > 0 && balanceShift) { - // Shift back to make the distribution more equally. - shiftList(-totalShifts / len, 0, len); - } // TODO bleedMargin? - - - var first = list[0]; - var last = list[len - 1]; - var minGap; - var maxGap; - updateMinMaxGap(); // If ends exceed two bounds, squeeze at most 80%, then take the gap of two bounds. - - minGap < 0 && squeezeGaps(-minGap, 0.8); - maxGap < 0 && squeezeGaps(maxGap, 0.8); - updateMinMaxGap(); - takeBoundsGap(minGap, maxGap, 1); - takeBoundsGap(maxGap, minGap, -1); // Handle bailout when there is not enough space. - - updateMinMaxGap(); - - if (minGap < 0) { - squeezeWhenBailout(-minGap); - } - - if (maxGap < 0) { - squeezeWhenBailout(maxGap); - } - - function updateMinMaxGap() { - minGap = first.rect[xyDim] - minBound; - maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim]; - } - - function takeBoundsGap(gapThisBound, gapOtherBound, moveDir) { - if (gapThisBound < 0) { - // Move from other gap if can. - var moveFromMaxGap = Math.min(gapOtherBound, -gapThisBound); - - if (moveFromMaxGap > 0) { - shiftList(moveFromMaxGap * moveDir, 0, len); - var remained = moveFromMaxGap + gapThisBound; - - if (remained < 0) { - squeezeGaps(-remained * moveDir, 1); - } - } else { - squeezeGaps(-gapThisBound * moveDir, 1); - } - } - } - - function shiftList(delta, start, end) { - if (delta !== 0) { - adjusted = true; - } - - for (var i = start; i < end; i++) { - var item = list[i]; - var rect = item.rect; - rect[xyDim] += delta; - item.label[xyDim] += delta; - } - } // Squeeze gaps if the labels exceed margin. - - - function squeezeGaps(delta, maxSqeezePercent) { - var gaps = []; - var totalGaps = 0; - - for (var i = 1; i < len; i++) { - var prevItemRect = list[i - 1].rect; - var gap = Math.max(list[i].rect[xyDim] - prevItemRect[xyDim] - prevItemRect[sizeDim], 0); - gaps.push(gap); - totalGaps += gap; - } - - if (!totalGaps) { - return; - } - - var squeezePercent = Math.min(Math.abs(delta) / totalGaps, maxSqeezePercent); - - if (delta > 0) { - for (var i = 0; i < len - 1; i++) { - // Distribute the shift delta to all gaps. - var movement = gaps[i] * squeezePercent; // Forward - - shiftList(movement, 0, i + 1); - } - } else { - // Backward - for (var i = len - 1; i > 0; i--) { - // Distribute the shift delta to all gaps. - var movement = gaps[i - 1] * squeezePercent; - shiftList(-movement, i, len); - } - } - } - /** - * Squeeze to allow overlap if there is no more space available. - * Let other overlapping strategy like hideOverlap do the job instead of keep exceeding the bounds. - */ - - - function squeezeWhenBailout(delta) { - var dir = delta < 0 ? -1 : 1; - delta = Math.abs(delta); - var moveForEachLabel = Math.ceil(delta / (len - 1)); - - for (var i = 0; i < len - 1; i++) { - if (dir > 0) { - // Forward - shiftList(moveForEachLabel, 0, i + 1); - } else { - // Backward - shiftList(-moveForEachLabel, len - i - 1, len); - } - - delta -= moveForEachLabel; - - if (delta <= 0) { - return; - } - } - } - - return adjusted; - } - /** - * Adjust labels on x direction to avoid overlap. - */ - - - function shiftLayoutOnX(list, leftBound, rightBound, // If average the shifts on all labels and add them to 0 - // TODO: Not sure if should enable it. - // Pros: The angle of lines will distribute more equally - // Cons: In some layout. It may not what user wanted. like in pie. the label of last sector is usually changed unexpectedly. - balanceShift) { - return shiftLayout(list, 'x', 'width', leftBound, rightBound, balanceShift); - } - /** - * Adjust labels on y direction to avoid overlap. - */ - - - function shiftLayoutOnY(list, topBound, bottomBound, // If average the shifts on all labels and add them to 0 - balanceShift) { - return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift); - } - - function hideOverlap(labelList) { - var displayedLabels = []; // TODO, render overflow visible first, put in the displayedLabels. - - labelList.sort(function (a, b) { - return b.priority - a.priority; - }); - var globalRect = new BoundingRect(0, 0, 0, 0); - - function hideEl(el) { - if (!el.ignore) { - // Show on emphasis. - var emphasisState = el.ensureState('emphasis'); - - if (emphasisState.ignore == null) { - emphasisState.ignore = false; - } - } - - el.ignore = true; - } - - for (var i = 0; i < labelList.length; i++) { - var labelItem = labelList[i]; - var isAxisAligned = labelItem.axisAligned; - var localRect = labelItem.localRect; - var transform = labelItem.transform; - var label = labelItem.label; - var labelLine = labelItem.labelLine; - globalRect.copy(labelItem.rect); // Add a threshold because layout may be aligned precisely. - - globalRect.width -= 0.1; - globalRect.height -= 0.1; - globalRect.x += 0.05; - globalRect.y += 0.05; - var obb = labelItem.obb; - var overlapped = false; - - for (var j = 0; j < displayedLabels.length; j++) { - var existsTextCfg = displayedLabels[j]; // Fast rejection. - - if (!globalRect.intersect(existsTextCfg.rect)) { - continue; - } - - if (isAxisAligned && existsTextCfg.axisAligned) { - // Is overlapped - overlapped = true; - break; - } - - if (!existsTextCfg.obb) { - // If self is not axis aligned. But other is. - existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform); - } - - if (!obb) { - // If self is axis aligned. But other is not. - obb = new OrientedBoundingRect(localRect, transform); - } - - if (obb.intersect(existsTextCfg.obb)) { - overlapped = true; - break; - } - } // TODO Callback to determine if this overlap should be handled? - - - if (overlapped) { - hideEl(label); - labelLine && hideEl(labelLine); - } else { - label.attr('ignore', labelItem.defaultAttr.ignore); - labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore); - displayedLabels.push(labelItem); - } - } - } - - function cloneArr(points) { - if (points) { - var newPoints = []; - - for (var i = 0; i < points.length; i++) { - newPoints.push(points[i].slice()); - } - - return newPoints; - } - } - - function prepareLayoutCallbackParams(labelItem, hostEl) { - var label = labelItem.label; - var labelLine = hostEl && hostEl.getTextGuideLine(); - return { - dataIndex: labelItem.dataIndex, - dataType: labelItem.dataType, - seriesIndex: labelItem.seriesModel.seriesIndex, - text: labelItem.label.style.text, - rect: labelItem.hostRect, - labelRect: labelItem.rect, - // x: labelAttr.x, - // y: labelAttr.y, - align: label.style.align, - verticalAlign: label.style.verticalAlign, - labelLinePoints: cloneArr(labelLine && labelLine.shape.points) - }; - } - - var LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize']; - var dummyTransformable = new Transformable(); - var labelLayoutInnerStore = makeInner(); - var labelLineAnimationStore = makeInner(); - - function extendWithKeys(target, source, keys) { - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - - if (source[key] != null) { - target[key] = source[key]; - } - } - } - - var LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation']; - - var LabelManager = - /** @class */ - function () { - function LabelManager() { - this._labelList = []; - this._chartViewList = []; - } - - LabelManager.prototype.clearLabels = function () { - this._labelList = []; - this._chartViewList = []; - }; - /** - * Add label to manager - */ - - - LabelManager.prototype._addLabel = function (dataIndex, dataType, seriesModel, label, layoutOption) { - var labelStyle = label.style; - var hostEl = label.__hostTarget; - var textConfig = hostEl.textConfig || {}; // TODO: If label is in other state. - - var labelTransform = label.getComputedTransform(); - var labelRect = label.getBoundingRect().plain(); - BoundingRect.applyTransform(labelRect, labelRect, labelTransform); - - if (labelTransform) { - dummyTransformable.setLocalTransform(labelTransform); - } else { - // Identity transform. - dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation = dummyTransformable.originX = dummyTransformable.originY = 0; - dummyTransformable.scaleX = dummyTransformable.scaleY = 1; - } - - dummyTransformable.rotation = normalizeRadian(dummyTransformable.rotation); - var host = label.__hostTarget; - var hostRect; - - if (host) { - hostRect = host.getBoundingRect().plain(); - var transform = host.getComputedTransform(); - BoundingRect.applyTransform(hostRect, hostRect, transform); - } - - var labelGuide = hostRect && host.getTextGuideLine(); - - this._labelList.push({ - label: label, - labelLine: labelGuide, - seriesModel: seriesModel, - dataIndex: dataIndex, - dataType: dataType, - layoutOption: layoutOption, - computedLayoutOption: null, - rect: labelRect, - hostRect: hostRect, - // Label with lower priority will be hidden when overlapped - // Use rect size as default priority - priority: hostRect ? hostRect.width * hostRect.height : 0, - // Save default label attributes. - // For restore if developers want get back to default value in callback. - defaultAttr: { - ignore: label.ignore, - labelGuideIgnore: labelGuide && labelGuide.ignore, - x: dummyTransformable.x, - y: dummyTransformable.y, - scaleX: dummyTransformable.scaleX, - scaleY: dummyTransformable.scaleY, - rotation: dummyTransformable.rotation, - style: { - x: labelStyle.x, - y: labelStyle.y, - align: labelStyle.align, - verticalAlign: labelStyle.verticalAlign, - width: labelStyle.width, - height: labelStyle.height, - fontSize: labelStyle.fontSize - }, - cursor: label.cursor, - attachedPos: textConfig.position, - attachedRot: textConfig.rotation - } - }); - }; - - LabelManager.prototype.addLabelsOfSeries = function (chartView) { - var _this = this; - - this._chartViewList.push(chartView); - - var seriesModel = chartView.__model; - var layoutOption = seriesModel.get('labelLayout'); - /** - * Ignore layouting if it's not specified anything. - */ - - if (!(isFunction(layoutOption) || keys(layoutOption).length)) { - return; - } - - chartView.group.traverse(function (child) { - if (child.ignore) { - return true; // Stop traverse descendants. - } // Only support label being hosted on graphic elements. - - - var textEl = child.getTextContent(); - var ecData = getECData(child); // Can only attach the text on the element with dataIndex - - if (textEl && !textEl.disableLabelLayout) { - _this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption); - } - }); - }; - - LabelManager.prototype.updateLayoutConfig = function (api) { - var width = api.getWidth(); - var height = api.getHeight(); - - function createDragHandler(el, labelLineModel) { - return function () { - updateLabelLinePoints(el, labelLineModel); - }; - } - - for (var i = 0; i < this._labelList.length; i++) { - var labelItem = this._labelList[i]; - var label = labelItem.label; - var hostEl = label.__hostTarget; - var defaultLabelAttr = labelItem.defaultAttr; - var layoutOption = void 0; // TODO A global layout option? - - if (isFunction(labelItem.layoutOption)) { - layoutOption = labelItem.layoutOption(prepareLayoutCallbackParams(labelItem, hostEl)); - } else { - layoutOption = labelItem.layoutOption; - } - - layoutOption = layoutOption || {}; - labelItem.computedLayoutOption = layoutOption; - var degreeToRadian = Math.PI / 180; // TODO hostEl should always exists. - // Or label should not have parent because the x, y is all in global space. - - if (hostEl) { - hostEl.setTextConfig({ - // Force to set local false. - local: false, - // Ignore position and rotation config on the host el if x or y is changed. - position: layoutOption.x != null || layoutOption.y != null ? null : defaultLabelAttr.attachedPos, - // Ignore rotation config on the host el if rotation is changed. - rotation: layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot, - offset: [layoutOption.dx || 0, layoutOption.dy || 0] - }); - } - - var needsUpdateLabelLine = false; - - if (layoutOption.x != null) { - // TODO width of chart view. - label.x = parsePercent(layoutOption.x, width); - label.setStyle('x', 0); // Ignore movement in style. TODO: origin. - - needsUpdateLabelLine = true; - } else { - label.x = defaultLabelAttr.x; - label.setStyle('x', defaultLabelAttr.style.x); - } - - if (layoutOption.y != null) { - // TODO height of chart view. - label.y = parsePercent(layoutOption.y, height); - label.setStyle('y', 0); // Ignore movement in style. - - needsUpdateLabelLine = true; - } else { - label.y = defaultLabelAttr.y; - label.setStyle('y', defaultLabelAttr.style.y); - } - - if (layoutOption.labelLinePoints) { - var guideLine = hostEl.getTextGuideLine(); - - if (guideLine) { - guideLine.setShape({ - points: layoutOption.labelLinePoints - }); // Not update - - needsUpdateLabelLine = false; - } - } - - var labelLayoutStore = labelLayoutInnerStore(label); - labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine; - label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation; - label.scaleX = defaultLabelAttr.scaleX; - label.scaleY = defaultLabelAttr.scaleY; - - for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) { - var key = LABEL_OPTION_TO_STYLE_KEYS[k]; - label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]); - } - - if (layoutOption.draggable) { - label.draggable = true; - label.cursor = 'move'; - - if (hostEl) { - var hostModel = labelItem.seriesModel; - - if (labelItem.dataIndex != null) { - var data = labelItem.seriesModel.getData(labelItem.dataType); - hostModel = data.getItemModel(labelItem.dataIndex); - } - - label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine'))); - } - } else { - // TODO Other drag functions? - label.off('drag'); - label.cursor = defaultLabelAttr.cursor; - } - } - }; - - LabelManager.prototype.layout = function (api) { - var width = api.getWidth(); - var height = api.getHeight(); - var labelList = prepareLayoutList(this._labelList); - var labelsNeedsAdjustOnX = filter(labelList, function (item) { - return item.layoutOption.moveOverlap === 'shiftX'; - }); - var labelsNeedsAdjustOnY = filter(labelList, function (item) { - return item.layoutOption.moveOverlap === 'shiftY'; - }); - shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width); - shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height); - var labelsNeedsHideOverlap = filter(labelList, function (item) { - return item.layoutOption.hideOverlap; - }); - hideOverlap(labelsNeedsHideOverlap); - }; - /** - * Process all labels. Not only labels with layoutOption. - */ - - - LabelManager.prototype.processLabelsOverall = function () { - var _this = this; - - each$4(this._chartViewList, function (chartView) { - var seriesModel = chartView.__model; - var ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate; - var animationEnabled = seriesModel.isAnimationEnabled(); - chartView.group.traverse(function (child) { - if (child.ignore && !child.forceLabelAnimation) { - return true; // Stop traverse descendants. - } - - var needsUpdateLabelLine = !ignoreLabelLineUpdate; - var label = child.getTextContent(); - - if (!needsUpdateLabelLine && label) { - needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine; - } - - if (needsUpdateLabelLine) { - _this._updateLabelLine(child, seriesModel); - } - - if (animationEnabled) { - _this._animateLabels(child, seriesModel); - } - }); - }); - }; - - LabelManager.prototype._updateLabelLine = function (el, seriesModel) { - // Only support label being hosted on graphic elements. - var textEl = el.getTextContent(); // Update label line style. - - var ecData = getECData(el); - var dataIndex = ecData.dataIndex; // Only support labelLine on the labels represent data. - - if (textEl && dataIndex != null) { - var data = seriesModel.getData(ecData.dataType); - var itemModel = data.getItemModel(dataIndex); - var defaultStyle = {}; - var visualStyle = data.getItemVisual(dataIndex, 'style'); - - if (visualStyle) { - var visualType = data.getVisual('drawType'); // Default to be same with main color - - defaultStyle.stroke = visualStyle[visualType]; - } - - var labelLineModel = itemModel.getModel('labelLine'); - setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle); - updateLabelLinePoints(el, labelLineModel); - } - }; - - LabelManager.prototype._animateLabels = function (el, seriesModel) { - var textEl = el.getTextContent(); - var guideLine = el.getTextGuideLine(); // Animate - - if (textEl // `forceLabelAnimation` has the highest priority - && (el.forceLabelAnimation || !textEl.ignore && !textEl.invisible && !el.disableLabelAnimation && !isElementRemoved(el))) { - var layoutStore = labelLayoutInnerStore(textEl); - var oldLayout = layoutStore.oldLayout; - var ecData = getECData(el); - var dataIndex = ecData.dataIndex; - var newProps = { - x: textEl.x, - y: textEl.y, - rotation: textEl.rotation - }; - var data = seriesModel.getData(ecData.dataType); - - if (!oldLayout) { - textEl.attr(newProps); // Disable fade in animation if value animation is enabled. - - if (!labelInner(textEl).valueAnimation) { - var oldOpacity = retrieve2(textEl.style.opacity, 1); // Fade in animation - - textEl.style.opacity = 0; - initProps(textEl, { - style: { - opacity: oldOpacity - } - }, seriesModel, dataIndex); - } - } else { - textEl.attr(oldLayout); // Make sure the animation from is in the right status. - - var prevStates = el.prevStates; - - if (prevStates) { - if (indexOf(prevStates, 'select') >= 0) { - textEl.attr(layoutStore.oldLayoutSelect); - } - - if (indexOf(prevStates, 'emphasis') >= 0) { - textEl.attr(layoutStore.oldLayoutEmphasis); - } - } - - updateProps$1(textEl, newProps, seriesModel, dataIndex); - } - - layoutStore.oldLayout = newProps; - - if (textEl.states.select) { - var layoutSelect = layoutStore.oldLayoutSelect = {}; - extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS); - extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS); - } - - if (textEl.states.emphasis) { - var layoutEmphasis = layoutStore.oldLayoutEmphasis = {}; - extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS); - extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS); - } - - animateLabelValue(textEl, dataIndex, data, seriesModel, seriesModel); - } - - if (guideLine && !guideLine.ignore && !guideLine.invisible) { - var layoutStore = labelLineAnimationStore(guideLine); - var oldLayout = layoutStore.oldLayout; - var newLayout = { - points: guideLine.shape.points - }; - - if (!oldLayout) { - guideLine.setShape(newLayout); - guideLine.style.strokePercent = 0; - initProps(guideLine, { - style: { - strokePercent: 1 - } - }, seriesModel); - } else { - guideLine.attr({ - shape: oldLayout - }); - updateProps$1(guideLine, { - shape: newLayout - }, seriesModel); - } - - layoutStore.oldLayout = newLayout; - } - }; - - return LabelManager; - }(); - - var getLabelManager = makeInner(); - - function installLabelLayout(registers) { - registers.registerUpdateLifecycle('series:beforeupdate', function (ecModel, api, params) { - // TODO api provide an namespace that can save stuff per instance - var labelManager = getLabelManager(api).labelManager; - - if (!labelManager) { - labelManager = getLabelManager(api).labelManager = new LabelManager(); - } - - labelManager.clearLabels(); - }); - registers.registerUpdateLifecycle('series:layoutlabels', function (ecModel, api, params) { - var labelManager = getLabelManager(api).labelManager; - params.updatedSeries.forEach(function (series) { - labelManager.addLabelsOfSeries(api.getViewOfSeriesModel(series)); - }); - labelManager.updateLayoutConfig(api); - labelManager.layout(api); - labelManager.processLabelsOverall(); - }); - } - - use(installLabelLayout); - - function createDom(id, painter, dpr) { - var newDom = platformApi.createCanvas(); - var width = painter.getWidth(); - var height = painter.getHeight(); - var newDomStyle = newDom.style; - - if (newDomStyle) { - newDomStyle.position = 'absolute'; - newDomStyle.left = '0'; - newDomStyle.top = '0'; - newDomStyle.width = width + 'px'; - newDomStyle.height = height + 'px'; - newDom.setAttribute('data-zr-dom-id', id); - } - - newDom.width = width * dpr; - newDom.height = height * dpr; - return newDom; - } - - var Layer = function (_super) { - __extends(Layer, _super); - - function Layer(id, painter, dpr) { - var _this = _super.call(this) || this; - - _this.motionBlur = false; - _this.lastFrameAlpha = 0.7; - _this.dpr = 1; - _this.virtual = false; - _this.config = {}; - _this.incremental = false; - _this.zlevel = 0; - _this.maxRepaintRectCount = 5; - _this.__dirty = true; - _this.__firstTimePaint = true; - _this.__used = false; - _this.__drawIndex = 0; - _this.__startIndex = 0; - _this.__endIndex = 0; - _this.__prevStartIndex = null; - _this.__prevEndIndex = null; - var dom; - dpr = dpr || devicePixelRatio; - - if (typeof id === 'string') { - dom = createDom(id, painter, dpr); - } else if (isObject$2(id)) { - dom = id; - id = dom.id; - } - - _this.id = id; - _this.dom = dom; - var domStyle = dom.style; - - if (domStyle) { - disableUserSelect(dom); - - dom.onselectstart = function () { - return false; - }; - - domStyle.padding = '0'; - domStyle.margin = '0'; - domStyle.borderWidth = '0'; - } - - _this.painter = painter; - _this.dpr = dpr; - return _this; - } - - Layer.prototype.getElementCount = function () { - return this.__endIndex - this.__startIndex; - }; - - Layer.prototype.afterBrush = function () { - this.__prevStartIndex = this.__startIndex; - this.__prevEndIndex = this.__endIndex; - }; - - Layer.prototype.initContext = function () { - this.ctx = this.dom.getContext('2d'); - this.ctx.dpr = this.dpr; - }; - - Layer.prototype.setUnpainted = function () { - this.__firstTimePaint = true; - }; - - Layer.prototype.createBackBuffer = function () { - var dpr = this.dpr; - this.domBack = createDom('back-' + this.id, this.painter, dpr); - this.ctxBack = this.domBack.getContext('2d'); - - if (dpr !== 1) { - this.ctxBack.scale(dpr, dpr); - } - }; - - Layer.prototype.createRepaintRects = function (displayList, prevList, viewWidth, viewHeight) { - if (this.__firstTimePaint) { - this.__firstTimePaint = false; - return null; - } - - var mergedRepaintRects = []; - var maxRepaintRectCount = this.maxRepaintRectCount; - var full = false; - var pendingRect = new BoundingRect(0, 0, 0, 0); - - function addRectToMergePool(rect) { - if (!rect.isFinite() || rect.isZero()) { - return; - } - - if (mergedRepaintRects.length === 0) { - var boundingRect = new BoundingRect(0, 0, 0, 0); - boundingRect.copy(rect); - mergedRepaintRects.push(boundingRect); - } else { - var isMerged = false; - var minDeltaArea = Infinity; - var bestRectToMergeIdx = 0; - - for (var i = 0; i < mergedRepaintRects.length; ++i) { - var mergedRect = mergedRepaintRects[i]; - - if (mergedRect.intersect(rect)) { - var pendingRect_1 = new BoundingRect(0, 0, 0, 0); - pendingRect_1.copy(mergedRect); - pendingRect_1.union(rect); - mergedRepaintRects[i] = pendingRect_1; - isMerged = true; - break; - } else if (full) { - pendingRect.copy(rect); - pendingRect.union(mergedRect); - var aArea = rect.width * rect.height; - var bArea = mergedRect.width * mergedRect.height; - var pendingArea = pendingRect.width * pendingRect.height; - var deltaArea = pendingArea - aArea - bArea; - - if (deltaArea < minDeltaArea) { - minDeltaArea = deltaArea; - bestRectToMergeIdx = i; - } - } - } - - if (full) { - mergedRepaintRects[bestRectToMergeIdx].union(rect); - isMerged = true; - } - - if (!isMerged) { - var boundingRect = new BoundingRect(0, 0, 0, 0); - boundingRect.copy(rect); - mergedRepaintRects.push(boundingRect); - } - - if (!full) { - full = mergedRepaintRects.length >= maxRepaintRectCount; - } - } - } - - for (var i = this.__startIndex; i < this.__endIndex; ++i) { - var el = displayList[i]; - - if (el) { - var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true); - var prevRect = el.__isRendered && (el.__dirty & REDRAW_BIT || !shouldPaint) ? el.getPrevPaintRect() : null; - - if (prevRect) { - addRectToMergePool(prevRect); - } - - var curRect = shouldPaint && (el.__dirty & REDRAW_BIT || !el.__isRendered) ? el.getPaintRect() : null; - - if (curRect) { - addRectToMergePool(curRect); - } - } - } - - for (var i = this.__prevStartIndex; i < this.__prevEndIndex; ++i) { - var el = prevList[i]; - var shouldPaint = el && el.shouldBePainted(viewWidth, viewHeight, true, true); - - if (el && (!shouldPaint || !el.__zr) && el.__isRendered) { - var prevRect = el.getPrevPaintRect(); - - if (prevRect) { - addRectToMergePool(prevRect); - } - } - } - - var hasIntersections; - - do { - hasIntersections = false; - - for (var i = 0; i < mergedRepaintRects.length;) { - if (mergedRepaintRects[i].isZero()) { - mergedRepaintRects.splice(i, 1); - continue; - } - - for (var j = i + 1; j < mergedRepaintRects.length;) { - if (mergedRepaintRects[i].intersect(mergedRepaintRects[j])) { - hasIntersections = true; - mergedRepaintRects[i].union(mergedRepaintRects[j]); - mergedRepaintRects.splice(j, 1); - } else { - j++; - } - } - - i++; - } - } while (hasIntersections); - - this._paintRects = mergedRepaintRects; - return mergedRepaintRects; - }; - - Layer.prototype.debugGetPaintRects = function () { - return (this._paintRects || []).slice(); - }; - - Layer.prototype.resize = function (width, height) { - var dpr = this.dpr; - var dom = this.dom; - var domStyle = dom.style; - var domBack = this.domBack; - - if (domStyle) { - domStyle.width = width + 'px'; - domStyle.height = height + 'px'; - } - - dom.width = width * dpr; - dom.height = height * dpr; - - if (domBack) { - domBack.width = width * dpr; - domBack.height = height * dpr; - - if (dpr !== 1) { - this.ctxBack.scale(dpr, dpr); - } - } - }; - - Layer.prototype.clear = function (clearAll, clearColor, repaintRects) { - var dom = this.dom; - var ctx = this.ctx; - var width = dom.width; - var height = dom.height; - clearColor = clearColor || this.clearColor; - var haveMotionBLur = this.motionBlur && !clearAll; - var lastFrameAlpha = this.lastFrameAlpha; - var dpr = this.dpr; - var self = this; - - if (haveMotionBLur) { - if (!this.domBack) { - this.createBackBuffer(); - } - - this.ctxBack.globalCompositeOperation = 'copy'; - this.ctxBack.drawImage(dom, 0, 0, width / dpr, height / dpr); - } - - var domBack = this.domBack; - - function doClear(x, y, width, height) { - ctx.clearRect(x, y, width, height); - - if (clearColor && clearColor !== 'transparent') { - var clearColorGradientOrPattern = void 0; - - if (isGradientObject(clearColor)) { - var shouldCache = clearColor.global || clearColor.__width === width && clearColor.__height === height; - clearColorGradientOrPattern = shouldCache && clearColor.__canvasGradient || getCanvasGradient(ctx, clearColor, { - x: 0, - y: 0, - width: width, - height: height - }); - clearColor.__canvasGradient = clearColorGradientOrPattern; - clearColor.__width = width; - clearColor.__height = height; - } else if (isImagePatternObject(clearColor)) { - clearColor.scaleX = clearColor.scaleX || dpr; - clearColor.scaleY = clearColor.scaleY || dpr; - clearColorGradientOrPattern = createCanvasPattern(ctx, clearColor, { - dirty: function () { - self.setUnpainted(); - self.painter.refresh(); - } - }); - } - - ctx.save(); - ctx.fillStyle = clearColorGradientOrPattern || clearColor; - ctx.fillRect(x, y, width, height); - ctx.restore(); - } - - if (haveMotionBLur) { - ctx.save(); - ctx.globalAlpha = lastFrameAlpha; - ctx.drawImage(domBack, x, y, width, height); - ctx.restore(); - } - } - - if (!repaintRects || haveMotionBLur) { - doClear(0, 0, width, height); - } else if (repaintRects.length) { - each$4(repaintRects, function (rect) { - doClear(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); - }); - } - }; - - return Layer; - }(Eventful); - - var HOVER_LAYER_ZLEVEL = 1e5; - var CANVAS_ZLEVEL = 314159; - var EL_AFTER_INCREMENTAL_INC = 0.01; - var INCREMENTAL_INC = 0.001; - - function isLayerValid(layer) { - if (!layer) { - return false; - } - - if (layer.__builtin__) { - return true; - } - - if (typeof layer.resize !== 'function' || typeof layer.refresh !== 'function') { - return false; - } - - return true; - } - - function createRoot(width, height) { - var domRoot = document.createElement('div'); - domRoot.style.cssText = ['position:relative', 'width:' + width + 'px', 'height:' + height + 'px', 'padding:0', 'margin:0', 'border-width:0'].join(';') + ';'; - return domRoot; - } - - var CanvasPainter = function () { - function CanvasPainter(root, storage, opts, id) { - this.type = 'canvas'; - this._zlevelList = []; - this._prevDisplayList = []; - this._layers = {}; - this._layerConfig = {}; - this._needsManuallyCompositing = false; - this.type = 'canvas'; - var singleCanvas = !root.nodeName || root.nodeName.toUpperCase() === 'CANVAS'; - this._opts = opts = extend({}, opts || {}); - this.dpr = opts.devicePixelRatio || devicePixelRatio; - this._singleCanvas = singleCanvas; - this.root = root; - var rootStyle = root.style; - - if (rootStyle) { - disableUserSelect(root); - root.innerHTML = ''; - } - - this.storage = storage; - var zlevelList = this._zlevelList; - this._prevDisplayList = []; - var layers = this._layers; - - if (!singleCanvas) { - this._width = getSize(root, 0, opts); - this._height = getSize(root, 1, opts); - var domRoot = this._domRoot = createRoot(this._width, this._height); - root.appendChild(domRoot); - } else { - var rootCanvas = root; - var width = rootCanvas.width; - var height = rootCanvas.height; - - if (opts.width != null) { - width = opts.width; - } - - if (opts.height != null) { - height = opts.height; - } - - this.dpr = opts.devicePixelRatio || 1; - rootCanvas.width = width * this.dpr; - rootCanvas.height = height * this.dpr; - this._width = width; - this._height = height; - var mainLayer = new Layer(rootCanvas, this, this.dpr); - mainLayer.__builtin__ = true; - mainLayer.initContext(); - layers[CANVAS_ZLEVEL] = mainLayer; - mainLayer.zlevel = CANVAS_ZLEVEL; - zlevelList.push(CANVAS_ZLEVEL); - this._domRoot = root; - } - } - - CanvasPainter.prototype.getType = function () { - return 'canvas'; - }; - - CanvasPainter.prototype.isSingleCanvas = function () { - return this._singleCanvas; - }; - - CanvasPainter.prototype.getViewportRoot = function () { - return this._domRoot; - }; - - CanvasPainter.prototype.getViewportRootOffset = function () { - var viewportRoot = this.getViewportRoot(); - - if (viewportRoot) { - return { - offsetLeft: viewportRoot.offsetLeft || 0, - offsetTop: viewportRoot.offsetTop || 0 - }; - } - }; - - CanvasPainter.prototype.refresh = function (paintAll) { - var list = this.storage.getDisplayList(true); - var prevList = this._prevDisplayList; - var zlevelList = this._zlevelList; - this._redrawId = Math.random(); - - this._paintList(list, prevList, paintAll, this._redrawId); - - for (var i = 0; i < zlevelList.length; i++) { - var z = zlevelList[i]; - var layer = this._layers[z]; - - if (!layer.__builtin__ && layer.refresh) { - var clearColor = i === 0 ? this._backgroundColor : null; - layer.refresh(clearColor); - } - } - - if (this._opts.useDirtyRect) { - this._prevDisplayList = list.slice(); - } - - return this; - }; - - CanvasPainter.prototype.refreshHover = function () { - this._paintHoverList(this.storage.getDisplayList(false)); - }; - - CanvasPainter.prototype._paintHoverList = function (list) { - var len = list.length; - var hoverLayer = this._hoverlayer; - hoverLayer && hoverLayer.clear(); - - if (!len) { - return; - } - - var scope = { - inHover: true, - viewWidth: this._width, - viewHeight: this._height - }; - var ctx; - - for (var i = 0; i < len; i++) { - var el = list[i]; - - if (el.__inHover) { - if (!hoverLayer) { - hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL); - } - - if (!ctx) { - ctx = hoverLayer.ctx; - ctx.save(); - } - - brush$1(ctx, el, scope, i === len - 1); - } - } - - if (ctx) { - ctx.restore(); - } - }; - - CanvasPainter.prototype.getHoverLayer = function () { - return this.getLayer(HOVER_LAYER_ZLEVEL); - }; - - CanvasPainter.prototype.paintOne = function (ctx, el) { - brushSingle(ctx, el); - }; - - CanvasPainter.prototype._paintList = function (list, prevList, paintAll, redrawId) { - if (this._redrawId !== redrawId) { - return; - } - - paintAll = paintAll || false; - - this._updateLayerStatus(list); - - var _a = this._doPaintList(list, prevList, paintAll), - finished = _a.finished, - needsRefreshHover = _a.needsRefreshHover; - - if (this._needsManuallyCompositing) { - this._compositeManually(); - } - - if (needsRefreshHover) { - this._paintHoverList(list); - } - - if (!finished) { - var self_1 = this; - requestAnimationFrame$1(function () { - self_1._paintList(list, prevList, paintAll, redrawId); - }); - } else { - this.eachLayer(function (layer) { - layer.afterBrush && layer.afterBrush(); - }); - } - }; - - CanvasPainter.prototype._compositeManually = function () { - var ctx = this.getLayer(CANVAS_ZLEVEL).ctx; - var width = this._domRoot.width; - var height = this._domRoot.height; - ctx.clearRect(0, 0, width, height); - this.eachBuiltinLayer(function (layer) { - if (layer.virtual) { - ctx.drawImage(layer.dom, 0, 0, width, height); - } - }); - }; - - CanvasPainter.prototype._doPaintList = function (list, prevList, paintAll) { - var _this = this; - - var layerList = []; - var useDirtyRect = this._opts.useDirtyRect; - - for (var zi = 0; zi < this._zlevelList.length; zi++) { - var zlevel = this._zlevelList[zi]; - var layer = this._layers[zlevel]; - - if (layer.__builtin__ && layer !== this._hoverlayer && (layer.__dirty || paintAll)) { - layerList.push(layer); - } - } - - var finished = true; - var needsRefreshHover = false; - - var _loop_1 = function (k) { - var layer = layerList[k]; - var ctx = layer.ctx; - var repaintRects = useDirtyRect && layer.createRepaintRects(list, prevList, this_1._width, this_1._height); - var start = paintAll ? layer.__startIndex : layer.__drawIndex; - var useTimer = !paintAll && layer.incremental && Date.now; - var startTime = useTimer && Date.now(); - var clearColor = layer.zlevel === this_1._zlevelList[0] ? this_1._backgroundColor : null; - - if (layer.__startIndex === layer.__endIndex) { - layer.clear(false, clearColor, repaintRects); - } else if (start === layer.__startIndex) { - var firstEl = list[start]; - - if (!firstEl.incremental || !firstEl.notClear || paintAll) { - layer.clear(false, clearColor, repaintRects); - } - } - - if (start === -1) { - console.error('For some unknown reason. drawIndex is -1'); - start = layer.__startIndex; - } - - var i; - - var repaint = function (repaintRect) { - var scope = { - inHover: false, - allClipped: false, - prevEl: null, - viewWidth: _this._width, - viewHeight: _this._height - }; - - for (i = start; i < layer.__endIndex; i++) { - var el = list[i]; - - if (el.__inHover) { - needsRefreshHover = true; - } - - _this._doPaintEl(el, layer, useDirtyRect, repaintRect, scope, i === layer.__endIndex - 1); - - if (useTimer) { - var dTime = Date.now() - startTime; - - if (dTime > 15) { - break; - } - } - } - - if (scope.prevElClipPaths) { - ctx.restore(); - } - }; - - if (repaintRects) { - if (repaintRects.length === 0) { - i = layer.__endIndex; - } else { - var dpr = this_1.dpr; - - for (var r = 0; r < repaintRects.length; ++r) { - var rect = repaintRects[r]; - ctx.save(); - ctx.beginPath(); - ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); - ctx.clip(); - repaint(rect); - ctx.restore(); - } - } - } else { - ctx.save(); - repaint(); - ctx.restore(); - } - - layer.__drawIndex = i; - - if (layer.__drawIndex < layer.__endIndex) { - finished = false; - } - }; - - var this_1 = this; - - for (var k = 0; k < layerList.length; k++) { - _loop_1(k); - } - - if (env.wxa) { - each$4(this._layers, function (layer) { - if (layer && layer.ctx && layer.ctx.draw) { - layer.ctx.draw(); - } - }); - } - - return { - finished: finished, - needsRefreshHover: needsRefreshHover - }; - }; - - CanvasPainter.prototype._doPaintEl = function (el, currentLayer, useDirtyRect, repaintRect, scope, isLast) { - var ctx = currentLayer.ctx; - - if (useDirtyRect) { - var paintRect = el.getPaintRect(); - - if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) { - brush$1(ctx, el, scope, isLast); - el.setPrevPaintRect(paintRect); - } - } else { - brush$1(ctx, el, scope, isLast); - } - }; - - CanvasPainter.prototype.getLayer = function (zlevel, virtual) { - if (this._singleCanvas && !this._needsManuallyCompositing) { - zlevel = CANVAS_ZLEVEL; - } - - var layer = this._layers[zlevel]; - - if (!layer) { - layer = new Layer('zr_' + zlevel, this, this.dpr); - layer.zlevel = zlevel; - layer.__builtin__ = true; - - if (this._layerConfig[zlevel]) { - merge(layer, this._layerConfig[zlevel], true); - } else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) { - merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true); - } - - if (virtual) { - layer.virtual = virtual; - } - - this.insertLayer(zlevel, layer); - layer.initContext(); - } - - return layer; - }; - - CanvasPainter.prototype.insertLayer = function (zlevel, layer) { - var layersMap = this._layers; - var zlevelList = this._zlevelList; - var len = zlevelList.length; - var domRoot = this._domRoot; - var prevLayer = null; - var i = -1; - - if (layersMap[zlevel]) { - { - logError('ZLevel ' + zlevel + ' has been used already'); - } - return; - } - - if (!isLayerValid(layer)) { - { - logError('Layer of zlevel ' + zlevel + ' is not valid'); - } - return; - } - - if (len > 0 && zlevel > zlevelList[0]) { - for (i = 0; i < len - 1; i++) { - if (zlevelList[i] < zlevel && zlevelList[i + 1] > zlevel) { - break; - } - } - - prevLayer = layersMap[zlevelList[i]]; - } - - zlevelList.splice(i + 1, 0, zlevel); - layersMap[zlevel] = layer; - - if (!layer.virtual) { - if (prevLayer) { - var prevDom = prevLayer.dom; - - if (prevDom.nextSibling) { - domRoot.insertBefore(layer.dom, prevDom.nextSibling); - } else { - domRoot.appendChild(layer.dom); - } - } else { - if (domRoot.firstChild) { - domRoot.insertBefore(layer.dom, domRoot.firstChild); - } else { - domRoot.appendChild(layer.dom); - } - } - } - - layer.painter || (layer.painter = this); - }; - - CanvasPainter.prototype.eachLayer = function (cb, context) { - var zlevelList = this._zlevelList; - - for (var i = 0; i < zlevelList.length; i++) { - var z = zlevelList[i]; - cb.call(context, this._layers[z], z); - } - }; - - CanvasPainter.prototype.eachBuiltinLayer = function (cb, context) { - var zlevelList = this._zlevelList; - - for (var i = 0; i < zlevelList.length; i++) { - var z = zlevelList[i]; - var layer = this._layers[z]; - - if (layer.__builtin__) { - cb.call(context, layer, z); - } - } - }; - - CanvasPainter.prototype.eachOtherLayer = function (cb, context) { - var zlevelList = this._zlevelList; - - for (var i = 0; i < zlevelList.length; i++) { - var z = zlevelList[i]; - var layer = this._layers[z]; - - if (!layer.__builtin__) { - cb.call(context, layer, z); - } - } - }; - - CanvasPainter.prototype.getLayers = function () { - return this._layers; - }; - - CanvasPainter.prototype._updateLayerStatus = function (list) { - this.eachBuiltinLayer(function (layer, z) { - layer.__dirty = layer.__used = false; - }); - - function updatePrevLayer(idx) { - if (prevLayer) { - if (prevLayer.__endIndex !== idx) { - prevLayer.__dirty = true; - } - - prevLayer.__endIndex = idx; - } - } - - if (this._singleCanvas) { - for (var i_1 = 1; i_1 < list.length; i_1++) { - var el = list[i_1]; - - if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) { - this._needsManuallyCompositing = true; - break; - } - } - } - - var prevLayer = null; - var incrementalLayerCount = 0; - var prevZlevel; - var i; - - for (i = 0; i < list.length; i++) { - var el = list[i]; - var zlevel = el.zlevel; - var layer = void 0; - - if (prevZlevel !== zlevel) { - prevZlevel = zlevel; - incrementalLayerCount = 0; - } - - if (el.incremental) { - layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing); - layer.incremental = true; - incrementalLayerCount = 1; - } else { - layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing); - } - - if (!layer.__builtin__) { - logError('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id); - } - - if (layer !== prevLayer) { - layer.__used = true; - - if (layer.__startIndex !== i) { - layer.__dirty = true; - } - - layer.__startIndex = i; - - if (!layer.incremental) { - layer.__drawIndex = i; - } else { - layer.__drawIndex = -1; - } - - updatePrevLayer(i); - prevLayer = layer; - } - - if (el.__dirty & REDRAW_BIT && !el.__inHover) { - layer.__dirty = true; - - if (layer.incremental && layer.__drawIndex < 0) { - layer.__drawIndex = i; - } - } - } - - updatePrevLayer(i); - this.eachBuiltinLayer(function (layer, z) { - if (!layer.__used && layer.getElementCount() > 0) { - layer.__dirty = true; - layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0; - } - - if (layer.__dirty && layer.__drawIndex < 0) { - layer.__drawIndex = layer.__startIndex; - } - }); - }; - - CanvasPainter.prototype.clear = function () { - this.eachBuiltinLayer(this._clearLayer); - return this; - }; - - CanvasPainter.prototype._clearLayer = function (layer) { - layer.clear(); - }; - - CanvasPainter.prototype.setBackgroundColor = function (backgroundColor) { - this._backgroundColor = backgroundColor; - each$4(this._layers, function (layer) { - layer.setUnpainted(); - }); - }; - - CanvasPainter.prototype.configLayer = function (zlevel, config) { - if (config) { - var layerConfig = this._layerConfig; - - if (!layerConfig[zlevel]) { - layerConfig[zlevel] = config; - } else { - merge(layerConfig[zlevel], config, true); - } - - for (var i = 0; i < this._zlevelList.length; i++) { - var _zlevel = this._zlevelList[i]; - - if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) { - var layer = this._layers[_zlevel]; - merge(layer, layerConfig[zlevel], true); - } - } - } - }; - - CanvasPainter.prototype.delLayer = function (zlevel) { - var layers = this._layers; - var zlevelList = this._zlevelList; - var layer = layers[zlevel]; - - if (!layer) { - return; - } - - layer.dom.parentNode.removeChild(layer.dom); - delete layers[zlevel]; - zlevelList.splice(indexOf(zlevelList, zlevel), 1); - }; - - CanvasPainter.prototype.resize = function (width, height) { - if (!this._domRoot.style) { - if (width == null || height == null) { - return; - } - - this._width = width; - this._height = height; - this.getLayer(CANVAS_ZLEVEL).resize(width, height); - } else { - var domRoot = this._domRoot; - domRoot.style.display = 'none'; - var opts = this._opts; - var root = this.root; - width != null && (opts.width = width); - height != null && (opts.height = height); - width = getSize(root, 0, opts); - height = getSize(root, 1, opts); - domRoot.style.display = ''; - - if (this._width !== width || height !== this._height) { - domRoot.style.width = width + 'px'; - domRoot.style.height = height + 'px'; - - for (var id in this._layers) { - if (this._layers.hasOwnProperty(id)) { - this._layers[id].resize(width, height); - } - } - - this.refresh(true); - } - - this._width = width; - this._height = height; - } - - return this; - }; - - CanvasPainter.prototype.clearLayer = function (zlevel) { - var layer = this._layers[zlevel]; - - if (layer) { - layer.clear(); - } - }; - - CanvasPainter.prototype.dispose = function () { - this.root.innerHTML = ''; - this.root = this.storage = this._domRoot = this._layers = null; - }; - - CanvasPainter.prototype.getRenderedCanvas = function (opts) { - opts = opts || {}; - - if (this._singleCanvas && !this._compositeManually) { - return this._layers[CANVAS_ZLEVEL].dom; - } - - var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr); - imageLayer.initContext(); - imageLayer.clear(false, opts.backgroundColor || this._backgroundColor); - var ctx = imageLayer.ctx; - - if (opts.pixelRatio <= this.dpr) { - this.refresh(); - var width_1 = imageLayer.dom.width; - var height_1 = imageLayer.dom.height; - this.eachLayer(function (layer) { - if (layer.__builtin__) { - ctx.drawImage(layer.dom, 0, 0, width_1, height_1); - } else if (layer.renderToCanvas) { - ctx.save(); - layer.renderToCanvas(ctx); - ctx.restore(); - } - }); - } else { - var scope = { - inHover: false, - viewWidth: this._width, - viewHeight: this._height - }; - var displayList = this.storage.getDisplayList(true); - - for (var i = 0, len = displayList.length; i < len; i++) { - var el = displayList[i]; - brush$1(ctx, el, scope, i === len - 1); - } - } - - return imageLayer.dom; - }; - - CanvasPainter.prototype.getWidth = function () { - return this._width; - }; - - CanvasPainter.prototype.getHeight = function () { - return this._height; - }; - - return CanvasPainter; - }(); - - function install$b(registers) { - registers.registerPainter('canvas', CanvasPainter); - } - - var DatasetModel = - /** @class */ - function (_super) { - __extends(DatasetModel, _super); - - function DatasetModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'dataset'; - return _this; - } - - DatasetModel.prototype.init = function (option, parentModel, ecModel) { - _super.prototype.init.call(this, option, parentModel, ecModel); - - this._sourceManager = new SourceManager(this); - disableTransformOptionMerge(this); - }; - - DatasetModel.prototype.mergeOption = function (newOption, ecModel) { - _super.prototype.mergeOption.call(this, newOption, ecModel); - - disableTransformOptionMerge(this); - }; - - DatasetModel.prototype.optionUpdated = function () { - this._sourceManager.dirty(); - }; - - DatasetModel.prototype.getSourceManager = function () { - return this._sourceManager; - }; - - DatasetModel.type = 'dataset'; - DatasetModel.defaultOption = { - seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN - }; - return DatasetModel; - }(ComponentModel); - - var DatasetView = - /** @class */ - function (_super) { - __extends(DatasetView, _super); - - function DatasetView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'dataset'; - return _this; - } - - DatasetView.type = 'dataset'; - return DatasetView; - }(ComponentView); - - function install$a(registers) { - registers.registerComponentModel(DatasetModel); - registers.registerComponentView(DatasetView); - } // Default to have canvas renderer and dataset for compitatble reason. - - - use([install$b, install$a]); - use(installLabelLayout); - var samplers = { - average: function (frame) { - var sum = 0; - var count = 0; - - for (var i = 0; i < frame.length; i++) { - if (!isNaN(frame[i])) { - sum += frame[i]; - count++; - } - } // Return NaN if count is 0 - - - return count === 0 ? NaN : sum / count; - }, - sum: function (frame) { - var sum = 0; - - for (var i = 0; i < frame.length; i++) { - // Ignore NaN - sum += frame[i] || 0; - } - - return sum; - }, - max: function (frame) { - var max = -Infinity; - - for (var i = 0; i < frame.length; i++) { - frame[i] > max && (max = frame[i]); - } // NaN will cause illegal axis extent. - - - return isFinite(max) ? max : NaN; - }, - min: function (frame) { - var min = Infinity; - - for (var i = 0; i < frame.length; i++) { - frame[i] < min && (min = frame[i]); - } // NaN will cause illegal axis extent. - - - return isFinite(min) ? min : NaN; - }, - minmax: function (frame) { - var turningPointAbsoluteValue = -Infinity; - var turningPointOriginalValue = -Infinity; - - for (var i = 0; i < frame.length; i++) { - var originalValue = frame[i]; - var absoluteValue = Math.abs(originalValue); - - if (absoluteValue > turningPointAbsoluteValue) { - turningPointAbsoluteValue = absoluteValue; - turningPointOriginalValue = originalValue; - } - } - - return isFinite(turningPointOriginalValue) ? turningPointOriginalValue : NaN; - }, - // TODO - // Median - nearest: function (frame) { - return frame[0]; - } - }; - - var indexSampler = function (frame) { - return Math.round(frame.length / 2); - }; - - function dataSample(seriesType) { - return { - seriesType: seriesType, - // FIXME:TS never used, so comment it - // modifyOutputEnd: true, - reset: function (seriesModel, ecModel, api) { - var data = seriesModel.getData(); - var sampling = seriesModel.get('sampling'); - var coordSys = seriesModel.coordinateSystem; - var count = data.count(); // Only cartesian2d support down sampling. Disable it when there is few data. - - if (count > 10 && coordSys.type === 'cartesian2d' && sampling) { - var baseAxis = coordSys.getBaseAxis(); - var valueAxis = coordSys.getOtherAxis(baseAxis); - var extent = baseAxis.getExtent(); - var dpr = api.getDevicePixelRatio(); // Coordinste system has been resized - - var size = Math.abs(extent[1] - extent[0]) * (dpr || 1); - var rate = Math.round(count / size); - - if (isFinite(rate) && rate > 1) { - if (sampling === 'lttb') { - seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate)); - } - - var sampler = void 0; - - if (isString(sampling)) { - sampler = samplers[sampling]; - } else if (isFunction(sampling)) { - sampler = sampling; - } - - if (sampler) { - // Only support sample the first dim mapped from value axis. - seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler)); - } - } - } - } - }; - } - - var BaseBarSeriesModel = - /** @class */ - function (_super) { - __extends(BaseBarSeriesModel, _super); - - function BaseBarSeriesModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = BaseBarSeriesModel.type; - return _this; - } - - BaseBarSeriesModel.prototype.getInitialData = function (option, ecModel) { - return createSeriesData(null, this, { - useEncodeDefaulter: true - }); - }; - - BaseBarSeriesModel.prototype.getMarkerPosition = function (value, dims, startingAtTick) { - var coordSys = this.coordinateSystem; - - if (coordSys && coordSys.clampData) { - // PENDING if clamp ? - var clampData_1 = coordSys.clampData(value); - var pt_1 = coordSys.dataToPoint(clampData_1); - - if (startingAtTick) { - each$4(coordSys.getAxes(), function (axis, idx) { - // If axis type is category, use tick coords instead - if (axis.type === 'category' && dims != null) { - var tickCoords = axis.getTicksCoords(); - var alignTicksWithLabel = axis.getTickModel().get('alignWithLabel'); - var targetTickId = clampData_1[idx]; // The index of rightmost tick of markArea is 1 larger than x1/y1 index - - var isEnd = dims[idx] === 'x1' || dims[idx] === 'y1'; - - if (isEnd && !alignTicksWithLabel) { - targetTickId += 1; - } // The only contains one tick, tickCoords is - // like [{coord: 0, tickValue: 0}, {coord: 0}] - // to the length should always be larger than 1 - - - if (tickCoords.length < 2) { - return; - } else if (tickCoords.length === 2) { - // The left value and right value of the axis are - // the same. coord is 0 in both items. Use the max - // value of the axis as the coord - pt_1[idx] = axis.toGlobalCoord(axis.getExtent()[isEnd ? 1 : 0]); - return; - } - - var leftCoord = void 0; - var coord = void 0; - var stepTickValue = 1; - - for (var i = 0; i < tickCoords.length; i++) { - var tickCoord = tickCoords[i].coord; // The last item of tickCoords doesn't contain - // tickValue - - var tickValue = i === tickCoords.length - 1 ? tickCoords[i - 1].tickValue + stepTickValue : tickCoords[i].tickValue; - - if (tickValue === targetTickId) { - coord = tickCoord; - break; - } else if (tickValue < targetTickId) { - leftCoord = tickCoord; - } else if (leftCoord != null && tickValue > targetTickId) { - coord = (tickCoord + leftCoord) / 2; - break; - } - - if (i === 1) { - // Here we assume the step of category axes is - // the same - stepTickValue = tickValue - tickCoords[0].tickValue; - } - } - - if (coord == null) { - if (!leftCoord) { - // targetTickId is smaller than all tick ids in the - // visible area, use the leftmost tick coord - coord = tickCoords[0].coord; - } else if (leftCoord) { - // targetTickId is larger than all tick ids in the - // visible area, use the rightmost tick coord - coord = tickCoords[tickCoords.length - 1].coord; - } - } - - pt_1[idx] = axis.toGlobalCoord(coord); - } - }); - } else { - var data = this.getData(); - var offset = data.getLayout('offset'); - var size = data.getLayout('size'); - var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1; - pt_1[offsetIndex] += offset + size / 2; - } - - return pt_1; - } - - return [NaN, NaN]; - }; - - BaseBarSeriesModel.type = 'series.__base_bar__'; - BaseBarSeriesModel.defaultOption = { - // zlevel: 0, - z: 2, - coordinateSystem: 'cartesian2d', - legendHoverLink: true, - // stack: null - // Cartesian coordinate system - // xAxisIndex: 0, - // yAxisIndex: 0, - barMinHeight: 0, - barMinAngle: 0, - // cursor: null, - large: false, - largeThreshold: 400, - progressive: 3e3, - progressiveChunkMode: 'mod' - }; - return BaseBarSeriesModel; - }(SeriesModel); - - SeriesModel.registerClass(BaseBarSeriesModel); - - var BarSeriesModel = - /** @class */ - function (_super) { - __extends(BarSeriesModel, _super); - - function BarSeriesModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = BarSeriesModel.type; - return _this; - } - - BarSeriesModel.prototype.getInitialData = function () { - return createSeriesData(null, this, { - useEncodeDefaulter: true, - createInvertedIndices: !!this.get('realtimeSort', true) || null - }); - }; - /** - * @override - */ - - - BarSeriesModel.prototype.getProgressive = function () { - // Do not support progressive in normal mode. - return this.get('large') ? this.get('progressive') : false; - }; - /** - * @override - */ - - - BarSeriesModel.prototype.getProgressiveThreshold = function () { - // Do not support progressive in normal mode. - var progressiveThreshold = this.get('progressiveThreshold'); - var largeThreshold = this.get('largeThreshold'); - - if (largeThreshold > progressiveThreshold) { - progressiveThreshold = largeThreshold; - } - - return progressiveThreshold; - }; - - BarSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { - return selectors.rect(data.getItemLayout(dataIndex)); - }; - - BarSeriesModel.type = 'series.bar'; - BarSeriesModel.dependencies = ['grid', 'polar']; - BarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, { - // If clipped - // Only available on cartesian2d - clip: true, - roundCap: false, - showBackground: false, - backgroundStyle: { - color: 'rgba(180, 180, 180, 0.2)', - borderColor: null, - borderWidth: 0, - borderType: 'solid', - borderRadius: 0, - shadowBlur: 0, - shadowColor: null, - shadowOffsetX: 0, - shadowOffsetY: 0, - opacity: 1 - }, - select: { - itemStyle: { - borderColor: '#212121' - } - }, - realtimeSort: false - }); - return BarSeriesModel; - }(BaseBarSeriesModel); - - function createGridClipPath(cartesian, hasAnimation, seriesModel, done, during) { - var rect = cartesian.getArea(); - var x = rect.x; - var y = rect.y; - var width = rect.width; - var height = rect.height; - var lineWidth = seriesModel.get(['lineStyle', 'width']) || 2; // Expand the clip path a bit to avoid the border is clipped and looks thinner - - x -= lineWidth / 2; - y -= lineWidth / 2; - width += lineWidth; - height += lineWidth; // fix: https://github.com/apache/incubator-echarts/issues/11369 - - width = Math.ceil(width); - - if (x !== Math.floor(x)) { - x = Math.floor(x); // if no extra 1px on `width`, it will still be clipped since `x` is floored - - width++; - } - - var clipPath = new Rect({ - shape: { - x: x, - y: y, - width: width, - height: height - } - }); - - if (hasAnimation) { - var baseAxis = cartesian.getBaseAxis(); - var isHorizontal = baseAxis.isHorizontal(); - var isAxisInversed = baseAxis.inverse; - - if (isHorizontal) { - if (isAxisInversed) { - clipPath.shape.x += width; - } - - clipPath.shape.width = 0; - } else { - if (!isAxisInversed) { - clipPath.shape.y += height; - } - - clipPath.shape.height = 0; - } - - var duringCb = isFunction(during) ? function (percent) { - during(percent, clipPath); - } : null; - initProps(clipPath, { - shape: { - width: width, - height: height, - x: x, - y: y - } - }, seriesModel, null, done, duringCb); - } - - return clipPath; - } - - function createPolarClipPath(polar, hasAnimation, seriesModel) { - var sectorArea = polar.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent. - - var r0 = round$2(sectorArea.r0, 1); - var r = round$2(sectorArea.r, 1); - var clipPath = new Sector({ - shape: { - cx: round$2(polar.cx, 1), - cy: round$2(polar.cy, 1), - r0: r0, - r: r, - startAngle: sectorArea.startAngle, - endAngle: sectorArea.endAngle, - clockwise: sectorArea.clockwise - } - }); - - if (hasAnimation) { - var isRadial = polar.getBaseAxis().dim === 'angle'; - - if (isRadial) { - clipPath.shape.endAngle = sectorArea.startAngle; - } else { - clipPath.shape.r = r0; - } - - initProps(clipPath, { - shape: { - endAngle: sectorArea.endAngle, - r: r - } - }, seriesModel); - } - - return clipPath; - } - - function createClipPath(coordSys, hasAnimation, seriesModel, done, during) { - if (!coordSys) { - return null; - } else if (coordSys.type === 'polar') { - return createPolarClipPath(coordSys, hasAnimation, seriesModel); - } else if (coordSys.type === 'cartesian2d') { - return createGridClipPath(coordSys, hasAnimation, seriesModel, done, during); - } - - return null; - } - /** - * Sausage: similar to sector, but have half circle on both sides - */ - - - var SausageShape = - /** @class */ - function () { - function SausageShape() { - this.cx = 0; - this.cy = 0; - this.r0 = 0; - this.r = 0; - this.startAngle = 0; - this.endAngle = Math.PI * 2; - this.clockwise = true; - } - - return SausageShape; - }(); - - var SausagePath = - /** @class */ - function (_super) { - __extends(SausagePath, _super); - - function SausagePath(opts) { - var _this = _super.call(this, opts) || this; - - _this.type = 'sausage'; - return _this; - } - - SausagePath.prototype.getDefaultShape = function () { - return new SausageShape(); - }; - - SausagePath.prototype.buildPath = function (ctx, shape) { - var cx = shape.cx; - var cy = shape.cy; - var r0 = Math.max(shape.r0 || 0, 0); - var r = Math.max(shape.r, 0); - var dr = (r - r0) * 0.5; - var rCenter = r0 + dr; - var startAngle = shape.startAngle; - var endAngle = shape.endAngle; - var clockwise = shape.clockwise; - var PI2 = Math.PI * 2; - var lessThanCircle = clockwise ? endAngle - startAngle < PI2 : startAngle - endAngle < PI2; - - if (!lessThanCircle) { - // Normalize angles - startAngle = endAngle - (clockwise ? PI2 : -PI2); - } - - var unitStartX = Math.cos(startAngle); - var unitStartY = Math.sin(startAngle); - var unitEndX = Math.cos(endAngle); - var unitEndY = Math.sin(endAngle); - - if (lessThanCircle) { - ctx.moveTo(unitStartX * r0 + cx, unitStartY * r0 + cy); - ctx.arc(unitStartX * rCenter + cx, unitStartY * rCenter + cy, dr, -Math.PI + startAngle, startAngle, !clockwise); - } else { - ctx.moveTo(unitStartX * r + cx, unitStartY * r + cy); - } - - ctx.arc(cx, cy, r, startAngle, endAngle, !clockwise); - ctx.arc(unitEndX * rCenter + cx, unitEndY * rCenter + cy, dr, endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise); - - if (r0 !== 0) { - ctx.arc(cx, cy, r0, endAngle, startAngle, clockwise); - } // ctx.closePath(); - - }; - - return SausagePath; - }(Path); - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - function isCoordinateSystemType(coordSys, type) { - return coordSys.type === type; - } - /** - * @return label string. Not null/undefined - */ - - - function getDefaultLabel(data, dataIndex) { - var labelDims = data.mapDimensionsAll('defaultedLabel'); - var len = labelDims.length; // Simple optimization (in lots of cases, label dims length is 1) - - if (len === 1) { - var rawVal = retrieveRawValue(data, dataIndex, labelDims[0]); - return rawVal != null ? rawVal + '' : null; - } else if (len) { - var vals = []; - - for (var i = 0; i < labelDims.length; i++) { - vals.push(retrieveRawValue(data, dataIndex, labelDims[i])); - } - - return vals.join(' '); - } - } - - function getDefaultInterpolatedLabel(data, interpolatedValue) { - var labelDims = data.mapDimensionsAll('defaultedLabel'); - - if (!isArray(interpolatedValue)) { - return interpolatedValue + ''; - } - - var vals = []; - - for (var i = 0; i < labelDims.length; i++) { - var dimIndex = data.getDimensionIndex(labelDims[i]); - - if (dimIndex >= 0) { - vals.push(interpolatedValue[dimIndex]); - } - } - - return vals.join(' '); - } - - function createSectorCalculateTextPosition(positionMapping, opts) { - opts = opts || {}; - var isRoundCap = opts.isRoundCap; - return function (out, opts, boundingRect) { - var textPosition = opts.position; - - if (!textPosition || textPosition instanceof Array) { - return calculateTextPosition(out, opts, boundingRect); - } - - var mappedSectorPosition = positionMapping(textPosition); - var distance = opts.distance != null ? opts.distance : 5; - var sector = this.shape; - var cx = sector.cx; - var cy = sector.cy; - var r = sector.r; - var r0 = sector.r0; - var middleR = (r + r0) / 2; - var startAngle = sector.startAngle; - var endAngle = sector.endAngle; - var middleAngle = (startAngle + endAngle) / 2; - var extraDist = isRoundCap ? Math.abs(r - r0) / 2 : 0; - var mathCos = Math.cos; - var mathSin = Math.sin; // base position: top-left - - var x = cx + r * mathCos(startAngle); - var y = cy + r * mathSin(startAngle); - var textAlign = 'left'; - var textVerticalAlign = 'top'; - - switch (mappedSectorPosition) { - case 'startArc': - x = cx + (r0 - distance) * mathCos(middleAngle); - y = cy + (r0 - distance) * mathSin(middleAngle); - textAlign = 'center'; - textVerticalAlign = 'top'; - break; - - case 'insideStartArc': - x = cx + (r0 + distance) * mathCos(middleAngle); - y = cy + (r0 + distance) * mathSin(middleAngle); - textAlign = 'center'; - textVerticalAlign = 'bottom'; - break; - - case 'startAngle': - x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, distance + extraDist, false); - y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, distance + extraDist, false); - textAlign = 'right'; - textVerticalAlign = 'middle'; - break; - - case 'insideStartAngle': - x = cx + middleR * mathCos(startAngle) + adjustAngleDistanceX(startAngle, -distance + extraDist, false); - y = cy + middleR * mathSin(startAngle) + adjustAngleDistanceY(startAngle, -distance + extraDist, false); - textAlign = 'left'; - textVerticalAlign = 'middle'; - break; - - case 'middle': - x = cx + middleR * mathCos(middleAngle); - y = cy + middleR * mathSin(middleAngle); - textAlign = 'center'; - textVerticalAlign = 'middle'; - break; - - case 'endArc': - x = cx + (r + distance) * mathCos(middleAngle); - y = cy + (r + distance) * mathSin(middleAngle); - textAlign = 'center'; - textVerticalAlign = 'bottom'; - break; - - case 'insideEndArc': - x = cx + (r - distance) * mathCos(middleAngle); - y = cy + (r - distance) * mathSin(middleAngle); - textAlign = 'center'; - textVerticalAlign = 'top'; - break; - - case 'endAngle': - x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, distance + extraDist, true); - y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, distance + extraDist, true); - textAlign = 'left'; - textVerticalAlign = 'middle'; - break; - - case 'insideEndAngle': - x = cx + middleR * mathCos(endAngle) + adjustAngleDistanceX(endAngle, -distance + extraDist, true); - y = cy + middleR * mathSin(endAngle) + adjustAngleDistanceY(endAngle, -distance + extraDist, true); - textAlign = 'right'; - textVerticalAlign = 'middle'; - break; - - default: - return calculateTextPosition(out, opts, boundingRect); - } - - out = out || {}; - out.x = x; - out.y = y; - out.align = textAlign; - out.verticalAlign = textVerticalAlign; - return out; - }; - } - - function setSectorTextRotation(sector, textPosition, positionMapping, rotateType) { - if (isNumber(rotateType)) { - // user-set rotation - sector.setTextConfig({ - rotation: rotateType - }); - return; - } else if (isArray(textPosition)) { - // user-set position, use 0 as auto rotation - sector.setTextConfig({ - rotation: 0 - }); - return; - } - - var shape = sector.shape; - var startAngle = shape.clockwise ? shape.startAngle : shape.endAngle; - var endAngle = shape.clockwise ? shape.endAngle : shape.startAngle; - var middleAngle = (startAngle + endAngle) / 2; - var anchorAngle; - var mappedSectorPosition = positionMapping(textPosition); - - switch (mappedSectorPosition) { - case 'startArc': - case 'insideStartArc': - case 'middle': - case 'insideEndArc': - case 'endArc': - anchorAngle = middleAngle; - break; - - case 'startAngle': - case 'insideStartAngle': - anchorAngle = startAngle; - break; - - case 'endAngle': - case 'insideEndAngle': - anchorAngle = endAngle; - break; - - default: - sector.setTextConfig({ - rotation: 0 - }); - return; - } - - var rotate = Math.PI * 1.5 - anchorAngle; - /** - * TODO: labels with rotate > Math.PI / 2 should be rotate another - * half round flipped to increase readability. However, only middle - * position supports this for now, because in other positions, the - * anchor point is not at the center of the text, so the positions - * after rotating is not as expected. - */ - - if (mappedSectorPosition === 'middle' && rotate > Math.PI / 2 && rotate < Math.PI * 1.5) { - rotate -= Math.PI; - } - - sector.setTextConfig({ - rotation: rotate - }); - } - - function adjustAngleDistanceX(angle, distance, isEnd) { - return distance * Math.sin(angle) * (isEnd ? -1 : 1); - } - - function adjustAngleDistanceY(angle, distance, isEnd) { - return distance * Math.cos(angle) * (isEnd ? 1 : -1); - } - - function getSectorCornerRadius(model, shape, zeroIfNull) { - var cornerRadius = model.get('borderRadius'); - - if (cornerRadius == null) { - return zeroIfNull ? { - cornerRadius: 0 - } : null; - } - - if (!isArray(cornerRadius)) { - cornerRadius = [cornerRadius, cornerRadius, cornerRadius, cornerRadius]; - } - - var dr = Math.abs(shape.r || 0 - shape.r0 || 0); - return { - cornerRadius: map$1(cornerRadius, function (cr) { - return parsePercent$1(cr, dr); - }) - }; - } - - var mathMax$1 = Math.max; - var mathMin$1 = Math.min; - - function getClipArea(coord, data) { - var coordSysClipArea = coord.getArea && coord.getArea(); - - if (isCoordinateSystemType(coord, 'cartesian2d')) { - var baseAxis = coord.getBaseAxis(); // When boundaryGap is false or using time axis. bar may exceed the grid. - // We should not clip this part. - // See test/bar2.html - - if (baseAxis.type !== 'category' || !baseAxis.onBand) { - var expandWidth = data.getLayout('bandWidth'); - - if (baseAxis.isHorizontal()) { - coordSysClipArea.x -= expandWidth; - coordSysClipArea.width += expandWidth * 2; - } else { - coordSysClipArea.y -= expandWidth; - coordSysClipArea.height += expandWidth * 2; - } - } - } - - return coordSysClipArea; - } - - var BarView = - /** @class */ - function (_super) { - __extends(BarView, _super); - - function BarView() { - var _this = _super.call(this) || this; - - _this.type = BarView.type; - _this._isFirstFrame = true; - return _this; - } - - BarView.prototype.render = function (seriesModel, ecModel, api, payload) { - this._model = seriesModel; - - this._removeOnRenderedListener(api); - - this._updateDrawMode(seriesModel); - - var coordinateSystemType = seriesModel.get('coordinateSystem'); - - if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') { - // Clear previously rendered progressive elements. - this._progressiveEls = null; - this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload); - } else { - warn('Only cartesian2d and polar supported for bar.'); - } - }; - - BarView.prototype.incrementalPrepareRender = function (seriesModel) { - this._clear(); - - this._updateDrawMode(seriesModel); // incremental also need to clip, otherwise might be overlow. - // But must not set clip in each frame, otherwise all of the children will be marked redraw. - - - this._updateLargeClip(seriesModel); - }; - - BarView.prototype.incrementalRender = function (params, seriesModel) { - // Reset - this._progressiveEls = []; // Do not support progressive in normal mode. - - this._incrementalRenderLarge(params, seriesModel); - }; - - BarView.prototype.eachRendered = function (cb) { - traverseElements(this._progressiveEls || this.group, cb); - }; - - BarView.prototype._updateDrawMode = function (seriesModel) { - var isLargeDraw = seriesModel.pipelineContext.large; - - if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { - this._isLargeDraw = isLargeDraw; - - this._clear(); - } - }; - - BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) { - var group = this.group; - var data = seriesModel.getData(); - var oldData = this._data; - var coord = seriesModel.coordinateSystem; - var baseAxis = coord.getBaseAxis(); - var isHorizontalOrRadial; - - if (coord.type === 'cartesian2d') { - isHorizontalOrRadial = baseAxis.isHorizontal(); - } else if (coord.type === 'polar') { - isHorizontalOrRadial = baseAxis.dim === 'angle'; - } - - var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; - var realtimeSortCfg = shouldRealtimeSort(seriesModel, coord); - - if (realtimeSortCfg) { - this._enableRealtimeSort(realtimeSortCfg, data, api); - } - - var needsClip = seriesModel.get('clip', true) || realtimeSortCfg; - var coordSysClipArea = getClipArea(coord, data); // If there is clipPath created in large mode. Remove it. - - group.removeClipPath(); // We don't use clipPath in normal mode because we needs a perfect animation - // And don't want the label are clipped. - - var roundCap = seriesModel.get('roundCap', true); - var drawBackground = seriesModel.get('showBackground', true); - var backgroundModel = seriesModel.getModel('backgroundStyle'); - var barBorderRadius = backgroundModel.get('borderRadius') || 0; - var bgEls = []; - var oldBgEls = this._backgroundEls; - var isInitSort = payload && payload.isInitSort; - var isChangeOrder = payload && payload.type === 'changeAxisOrder'; - - function createBackground(dataIndex) { - var bgLayout = getLayout[coord.type](data, dataIndex); - var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout); - bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. - - if (coord.type === 'cartesian2d') { - bgEl.setShape('r', barBorderRadius); - } else { - bgEl.setShape('cornerRadius', barBorderRadius); - } - - bgEls[dataIndex] = bgEl; - return bgEl; - } - - data.diff(oldData).add(function (dataIndex) { - var itemModel = data.getItemModel(dataIndex); - var layout = getLayout[coord.type](data, dataIndex, itemModel); - - if (drawBackground) { - createBackground(dataIndex); - } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy". - - - if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) { - return; - } - - var isClipped = false; - - if (needsClip) { - // Clip will modify the layout params. - // And return a boolean to determine if the shape are fully clipped. - isClipped = clip[coord.type](coordSysClipArea, layout); - } - - var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap); - - if (realtimeSortCfg) { - /** - * Force label animation because even if the element is - * ignored because it's clipped, it may not be clipped after - * changing order. Then, if not using forceLabelAnimation, - * the label animation was never started, in which case, - * the label will be the final value and doesn't have label - * animation. - */ - el.forceLabelAnimation = true; - } - - updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); - - if (isInitSort) { - el.attr({ - shape: layout - }); - } else if (realtimeSortCfg) { - updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false); - } else { - initProps(el, { - shape: layout - }, seriesModel, dataIndex); - } - - data.setItemGraphicEl(dataIndex, el); - group.add(el); - el.ignore = isClipped; - }).update(function (newIndex, oldIndex) { - var itemModel = data.getItemModel(newIndex); - var layout = getLayout[coord.type](data, newIndex, itemModel); - - if (drawBackground) { - var bgEl = void 0; - - if (oldBgEls.length === 0) { - bgEl = createBackground(oldIndex); - } else { - bgEl = oldBgEls[oldIndex]; - bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. - - if (coord.type === 'cartesian2d') { - bgEl.setShape('r', barBorderRadius); - } else { - bgEl.setShape('cornerRadius', barBorderRadius); - } - - bgEls[newIndex] = bgEl; - } - - var bgLayout = getLayout[coord.type](data, newIndex); - var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord); - updateProps$1(bgEl, { - shape: shape - }, animationModel, newIndex); - } - - var el = oldData.getItemGraphicEl(oldIndex); - - if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) { - group.remove(el); - return; - } - - var isClipped = false; - - if (needsClip) { - isClipped = clip[coord.type](coordSysClipArea, layout); - - if (isClipped) { - group.remove(el); - } - } - - if (!el) { - el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap); - } else { - saveOldStyle(el); - } - - if (realtimeSortCfg) { - el.forceLabelAnimation = true; - } - - if (isChangeOrder) { - var textEl = el.getTextContent(); - - if (textEl) { - var labelInnerStore = labelInner(textEl); - - if (labelInnerStore.prevValue != null) { - /** - * Set preValue to be value so that no new label - * should be started, otherwise, it will take a full - * `animationDurationUpdate` time to finish the - * animation, which is not expected. - */ - labelInnerStore.prevValue = labelInnerStore.value; - } - } - } // Not change anything if only order changed. - // Especially not change label. - else { - updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); - } - - if (isInitSort) { - el.attr({ - shape: layout - }); - } else if (realtimeSortCfg) { - updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder); - } else { - updateProps$1(el, { - shape: layout - }, seriesModel, newIndex, null); - } - - data.setItemGraphicEl(newIndex, el); - el.ignore = isClipped; - group.add(el); - }).remove(function (dataIndex) { - var el = oldData.getItemGraphicEl(dataIndex); - el && removeElementWithFadeOut(el, seriesModel, dataIndex); - }).execute(); - var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group$2()); - bgGroup.removeAll(); - - for (var i = 0; i < bgEls.length; ++i) { - bgGroup.add(bgEls[i]); - } - - group.add(bgGroup); - this._backgroundEls = bgEls; - this._data = data; - }; - - BarView.prototype._renderLarge = function (seriesModel, ecModel, api) { - this._clear(); - - createLarge(seriesModel, this.group); - - this._updateLargeClip(seriesModel); - }; - - BarView.prototype._incrementalRenderLarge = function (params, seriesModel) { - this._removeBackground(); - - createLarge(seriesModel, this.group, this._progressiveEls, true); - }; - - BarView.prototype._updateLargeClip = function (seriesModel) { - // Use clipPath in large mode. - var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel); - var group = this.group; - - if (clipPath) { - group.setClipPath(clipPath); - } else { - group.removeClipPath(); - } - }; - - BarView.prototype._enableRealtimeSort = function (realtimeSortCfg, data, api) { - var _this = this; // If no data in the first frame, wait for data to initSort - - - if (!data.count()) { - return; - } - - var baseAxis = realtimeSortCfg.baseAxis; - - if (this._isFirstFrame) { - this._dispatchInitSort(data, realtimeSortCfg, api); - - this._isFirstFrame = false; - } else { - var orderMapping_1 = function (idx) { - var el = data.getItemGraphicEl(idx); - var shape = el && el.shape; - return shape && // The result should be consistent with the initial sort by data value. - // Do not support the case that both positive and negative exist. - Math.abs(baseAxis.isHorizontal() ? shape.height : shape.width) // If data is NaN, shape.xxx may be NaN, so use || 0 here in case - || 0; - }; - - this._onRendered = function () { - _this._updateSortWithinSameData(data, orderMapping_1, baseAxis, api); - }; - - api.getZr().on('rendered', this._onRendered); - } - }; - - BarView.prototype._dataSort = function (data, baseAxis, orderMapping) { - var info = []; - data.each(data.mapDimension(baseAxis.dim), function (ordinalNumber, dataIdx) { - var mappedValue = orderMapping(dataIdx); - mappedValue = mappedValue == null ? NaN : mappedValue; - info.push({ - dataIndex: dataIdx, - mappedValue: mappedValue, - ordinalNumber: ordinalNumber - }); - }); - info.sort(function (a, b) { - // If NaN, it will be treated as min val. - return b.mappedValue - a.mappedValue; - }); - return { - ordinalNumbers: map$1(info, function (item) { - return item.ordinalNumber; - }) - }; - }; - - BarView.prototype._isOrderChangedWithinSameData = function (data, orderMapping, baseAxis) { - var scale = baseAxis.scale; - var ordinalDataDim = data.mapDimension(baseAxis.dim); - var lastValue = Number.MAX_VALUE; - - for (var tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) { - var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum)); - var value = rawIdx < 0 // If some tick have no bar, the tick will be treated as min. - ? Number.MIN_VALUE // PENDING: if dataZoom on baseAxis exits, is it a performance issue? - : orderMapping(data.indexOfRawIndex(rawIdx)); - - if (value > lastValue) { - return true; - } - - lastValue = value; - } - - return false; - }; - /* - * Consider the case when A and B changed order, whose representing - * bars are both out of sight, we don't wish to trigger reorder action - * as long as the order in the view doesn't change. - */ - - - BarView.prototype._isOrderDifferentInView = function (orderInfo, baseAxis) { - var scale = baseAxis.scale; - var extent = scale.getExtent(); - var tickNum = Math.max(0, extent[0]); - var tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1); - - for (; tickNum <= tickMax; ++tickNum) { - if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) { - return true; - } - } - }; - - BarView.prototype._updateSortWithinSameData = function (data, orderMapping, baseAxis, api) { - if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) { - return; - } - - var sortInfo = this._dataSort(data, baseAxis, orderMapping); - - if (this._isOrderDifferentInView(sortInfo, baseAxis)) { - this._removeOnRenderedListener(api); - - api.dispatchAction({ - type: 'changeAxisOrder', - componentType: baseAxis.dim + 'Axis', - axisId: baseAxis.index, - sortInfo: sortInfo - }); - } - }; - - BarView.prototype._dispatchInitSort = function (data, realtimeSortCfg, api) { - var baseAxis = realtimeSortCfg.baseAxis; - - var sortResult = this._dataSort(data, baseAxis, function (dataIdx) { - return data.get(data.mapDimension(realtimeSortCfg.otherAxis.dim), dataIdx); - }); - - api.dispatchAction({ - type: 'changeAxisOrder', - componentType: baseAxis.dim + 'Axis', - isInitSort: true, - axisId: baseAxis.index, - sortInfo: sortResult - }); - }; - - BarView.prototype.remove = function (ecModel, api) { - this._clear(this._model); - - this._removeOnRenderedListener(api); - }; - - BarView.prototype.dispose = function (ecModel, api) { - this._removeOnRenderedListener(api); - }; - - BarView.prototype._removeOnRenderedListener = function (api) { - if (this._onRendered) { - api.getZr().off('rendered', this._onRendered); - this._onRendered = null; - } - }; - - BarView.prototype._clear = function (model) { - var group = this.group; - var data = this._data; - - if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) { - this._removeBackground(); - - this._backgroundEls = []; - data.eachItemGraphicEl(function (el) { - removeElementWithFadeOut(el, model, getECData(el).dataIndex); - }); - } else { - group.removeAll(); - } - - this._data = null; - this._isFirstFrame = true; - }; - - BarView.prototype._removeBackground = function () { - this.group.remove(this._backgroundGroup); - this._backgroundGroup = null; - }; - - BarView.type = 'bar'; - return BarView; - }(ChartView); - - var clip = { - cartesian2d: function (coordSysBoundingRect, layout) { - var signWidth = layout.width < 0 ? -1 : 1; - var signHeight = layout.height < 0 ? -1 : 1; // Needs positive width and height - - if (signWidth < 0) { - layout.x += layout.width; - layout.width = -layout.width; - } - - if (signHeight < 0) { - layout.y += layout.height; - layout.height = -layout.height; - } - - var coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width; - var coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height; - var x = mathMax$1(layout.x, coordSysBoundingRect.x); - var x2 = mathMin$1(layout.x + layout.width, coordSysX2); - var y = mathMax$1(layout.y, coordSysBoundingRect.y); - var y2 = mathMin$1(layout.y + layout.height, coordSysY2); - var xClipped = x2 < x; - var yClipped = y2 < y; // When xClipped or yClipped, the element will be marked as `ignore`. - // But we should also place the element at the edge of the coord sys bounding rect. - // Because if data changed and the bar shows again, its transition animation - // will begin at this place. - - layout.x = xClipped && x > coordSysX2 ? x2 : x; - layout.y = yClipped && y > coordSysY2 ? y2 : y; - layout.width = xClipped ? 0 : x2 - x; - layout.height = yClipped ? 0 : y2 - y; // Reverse back - - if (signWidth < 0) { - layout.x += layout.width; - layout.width = -layout.width; - } - - if (signHeight < 0) { - layout.y += layout.height; - layout.height = -layout.height; - } - - return xClipped || yClipped; - }, - polar: function (coordSysClipArea, layout) { - var signR = layout.r0 <= layout.r ? 1 : -1; // Make sure r is larger than r0 - - if (signR < 0) { - var tmp = layout.r; - layout.r = layout.r0; - layout.r0 = tmp; - } - - var r = mathMin$1(layout.r, coordSysClipArea.r); - var r0 = mathMax$1(layout.r0, coordSysClipArea.r0); - layout.r = r; - layout.r0 = r0; - var clipped = r - r0 < 0; // Reverse back - - if (signR < 0) { - var tmp = layout.r; - layout.r = layout.r0; - layout.r0 = tmp; - } - - return clipped; - } - }; - var elementCreator = { - cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) { - var rect = new Rect({ - shape: extend({}, layout), - z2: 1 - }); - rect.__dataIndex = newIndex; - rect.name = 'item'; - - if (animationModel) { - var rectShape = rect.shape; - var animateProperty = isHorizontal ? 'height' : 'width'; - rectShape[animateProperty] = 0; - } - - return rect; - }, - polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) { - var ShapeClass = !isRadial && roundCap ? SausagePath : Sector; - var sector = new ShapeClass({ - shape: layout, - z2: 1 - }); - sector.name = 'item'; - var positionMap = createPolarPositionMapping(isRadial); - sector.calculateTextPosition = createSectorCalculateTextPosition(positionMap, { - isRoundCap: ShapeClass === SausagePath - }); // Animation - - if (animationModel) { - var sectorShape = sector.shape; - var animateProperty = isRadial ? 'r' : 'endAngle'; - var animateTarget = {}; - sectorShape[animateProperty] = isRadial ? layout.r0 : layout.startAngle; - animateTarget[animateProperty] = layout[animateProperty]; - (isUpdate ? updateProps$1 : initProps)(sector, { - shape: animateTarget // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue - - }, animationModel); - } - - return sector; - } - }; - - function shouldRealtimeSort(seriesModel, coordSys) { - var realtimeSortOption = seriesModel.get('realtimeSort', true); - var baseAxis = coordSys.getBaseAxis(); - { - if (realtimeSortOption) { - if (baseAxis.type !== 'category') { - warn('`realtimeSort` will not work because this bar series is not based on a category axis.'); - } - - if (coordSys.type !== 'cartesian2d') { - warn('`realtimeSort` will not work because this bar series is not on cartesian2d.'); - } - } - } - - if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') { - return { - baseAxis: baseAxis, - otherAxis: coordSys.getOtherAxis(baseAxis) - }; - } - } - - function updateRealtimeAnimation(realtimeSortCfg, seriesAnimationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) { - var seriesTarget; - var axisTarget; - - if (isHorizontal) { - axisTarget = { - x: layout.x, - width: layout.width - }; - seriesTarget = { - y: layout.y, - height: layout.height - }; - } else { - axisTarget = { - y: layout.y, - height: layout.height - }; - seriesTarget = { - x: layout.x, - width: layout.width - }; - } - - if (!isChangeOrder) { - // Keep the original growth animation if only axis order changed. - // Not start a new animation. - (isUpdate ? updateProps$1 : initProps)(el, { - shape: seriesTarget - }, seriesAnimationModel, newIndex, null); - } - - var axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null; - (isUpdate ? updateProps$1 : initProps)(el, { - shape: axisTarget - }, axisAnimationModel, newIndex); - } - - function checkPropertiesNotValid(obj, props) { - for (var i = 0; i < props.length; i++) { - if (!isFinite(obj[props[i]])) { - return true; - } - } - - return false; - } - - var rectPropties = ['x', 'y', 'width', 'height']; - var polarPropties = ['cx', 'cy', 'r', 'startAngle', 'endAngle']; - var isValidLayout = { - cartesian2d: function (layout) { - return !checkPropertiesNotValid(layout, rectPropties); - }, - polar: function (layout) { - return !checkPropertiesNotValid(layout, polarPropties); - } - }; - var getLayout = { - // itemModel is only used to get borderWidth, which is not needed - // when calculating bar background layout. - cartesian2d: function (data, dataIndex, itemModel) { - var layout = data.getItemLayout(dataIndex); - var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0; // fix layout with lineWidth - - var signX = layout.width > 0 ? 1 : -1; - var signY = layout.height > 0 ? 1 : -1; - return { - x: layout.x + signX * fixedLineWidth / 2, - y: layout.y + signY * fixedLineWidth / 2, - width: layout.width - signX * fixedLineWidth, - height: layout.height - signY * fixedLineWidth - }; - }, - polar: function (data, dataIndex, itemModel) { - var layout = data.getItemLayout(dataIndex); - return { - cx: layout.cx, - cy: layout.cy, - r0: layout.r0, - r: layout.r, - startAngle: layout.startAngle, - endAngle: layout.endAngle, - clockwise: layout.clockwise - }; - } - }; - - function isZeroOnPolar(layout) { - return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle; - } - - function createPolarPositionMapping(isRadial) { - return function (isRadial) { - var arcOrAngle = isRadial ? 'Arc' : 'Angle'; - return function (position) { - switch (position) { - case 'start': - case 'insideStart': - case 'end': - case 'insideEnd': - return position + arcOrAngle; - - default: - return position; - } - }; - }(isRadial); - } - - function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, isPolar) { - var style = data.getItemVisual(dataIndex, 'style'); - - if (!isPolar) { - var borderRadius = itemModel.get(['itemStyle', 'borderRadius']) || 0; - el.setShape('r', borderRadius); - } else if (!seriesModel.get('roundCap')) { - var sectorShape = el.shape; - var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape, true); - extend(sectorShape, cornerRadius); - el.setShape(sectorShape); - } - - el.useStyle(style); - var cursorStyle = itemModel.getShallow('cursor'); - cursorStyle && el.attr('cursor', cursorStyle); - var labelPositionOutside = isPolar ? isHorizontalOrRadial ? layout.r >= layout.r0 ? 'endArc' : 'startArc' : layout.endAngle >= layout.startAngle ? 'endAngle' : 'startAngle' : isHorizontalOrRadial ? layout.height >= 0 ? 'bottom' : 'top' : layout.width >= 0 ? 'right' : 'left'; - var labelStatesModels = getLabelStatesModels(itemModel); - setLabelStyle(el, labelStatesModels, { - labelFetcher: seriesModel, - labelDataIndex: dataIndex, - defaultText: getDefaultLabel(seriesModel.getData(), dataIndex), - inheritColor: style.fill, - defaultOpacity: style.opacity, - defaultOutsidePosition: labelPositionOutside - }); - var label = el.getTextContent(); - - if (isPolar && label) { - var position = itemModel.get(['label', 'position']); - el.textConfig.inside = position === 'middle' ? true : null; - setSectorTextRotation(el, position === 'outside' ? labelPositionOutside : position, createPolarPositionMapping(isHorizontalOrRadial), itemModel.get(['label', 'rotate'])); - } - - setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) { - return getDefaultInterpolatedLabel(data, value); - }); - var emphasisModel = itemModel.getModel(['emphasis']); - toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); - setStatesStylesFromModel(el, itemModel); - - if (isZeroOnPolar(layout)) { - el.style.fill = 'none'; - el.style.stroke = 'none'; - each$4(el.states, function (state) { - if (state.style) { - state.style.fill = state.style.stroke = 'none'; - } - }); - } - } // In case width or height are too small. - - - function getLineWidth(itemModel, rawLayout) { - // Has no border. - var borderColor = itemModel.get(['itemStyle', 'borderColor']); - - if (!borderColor || borderColor === 'none') { - return 0; - } - - var lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0; // width or height may be NaN for empty data - - var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width); - var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height); - return Math.min(lineWidth, width, height); - } - - var LagePathShape = - /** @class */ - function () { - function LagePathShape() {} - - return LagePathShape; - }(); - - var LargePath = - /** @class */ - function (_super) { - __extends(LargePath, _super); - - function LargePath(opts) { - var _this = _super.call(this, opts) || this; - - _this.type = 'largeBar'; - return _this; - } - - LargePath.prototype.getDefaultShape = function () { - return new LagePathShape(); - }; - - LargePath.prototype.buildPath = function (ctx, shape) { - // Drawing lines is more efficient than drawing - // a whole line or drawing rects. - var points = shape.points; - var baseDimIdx = this.baseDimIdx; - var valueDimIdx = 1 - this.baseDimIdx; - var startPoint = []; - var size = []; - var barWidth = this.barWidth; - - for (var i = 0; i < points.length; i += 3) { - size[baseDimIdx] = barWidth; - size[valueDimIdx] = points[i + 2]; - startPoint[baseDimIdx] = points[i + baseDimIdx]; - startPoint[valueDimIdx] = points[i + valueDimIdx]; - ctx.rect(startPoint[0], startPoint[1], size[0], size[1]); - } - }; - - return LargePath; - }(Path); - - function createLarge(seriesModel, group, progressiveEls, incremental) { - // TODO support polar - var data = seriesModel.getData(); - var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0; - var largeDataIndices = data.getLayout('largeDataIndices'); - var barWidth = data.getLayout('size'); - var backgroundModel = seriesModel.getModel('backgroundStyle'); - var bgPoints = data.getLayout('largeBackgroundPoints'); - - if (bgPoints) { - var bgEl = new LargePath({ - shape: { - points: bgPoints - }, - incremental: !!incremental, - silent: true, - z2: 0 - }); - bgEl.baseDimIdx = baseDimIdx; - bgEl.largeDataIndices = largeDataIndices; - bgEl.barWidth = barWidth; - bgEl.useStyle(backgroundModel.getItemStyle()); - group.add(bgEl); - progressiveEls && progressiveEls.push(bgEl); - } - - var el = new LargePath({ - shape: { - points: data.getLayout('largePoints') - }, - incremental: !!incremental, - ignoreCoarsePointer: true, - z2: 1 - }); - el.baseDimIdx = baseDimIdx; - el.largeDataIndices = largeDataIndices; - el.barWidth = barWidth; - group.add(el); - el.useStyle(data.getVisual('style')); // Enable tooltip and user mouse/touch event handlers. - - getECData(el).seriesIndex = seriesModel.seriesIndex; - - if (!seriesModel.get('silent')) { - el.on('mousedown', largePathUpdateDataIndex); - el.on('mousemove', largePathUpdateDataIndex); - } - - progressiveEls && progressiveEls.push(el); - } // Use throttle to avoid frequently traverse to find dataIndex. - - - var largePathUpdateDataIndex = throttle(function (event) { - var largePath = this; - var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY); - getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null; - }, 30, false); - - function largePathFindDataIndex(largePath, x, y) { - var baseDimIdx = largePath.baseDimIdx; - var valueDimIdx = 1 - baseDimIdx; - var points = largePath.shape.points; - var largeDataIndices = largePath.largeDataIndices; - var startPoint = []; - var size = []; - var barWidth = largePath.barWidth; - - for (var i = 0, len = points.length / 3; i < len; i++) { - var ii = i * 3; - size[baseDimIdx] = barWidth; - size[valueDimIdx] = points[ii + 2]; - startPoint[baseDimIdx] = points[ii + baseDimIdx]; - startPoint[valueDimIdx] = points[ii + valueDimIdx]; - - if (size[valueDimIdx] < 0) { - startPoint[valueDimIdx] += size[valueDimIdx]; - size[valueDimIdx] = -size[valueDimIdx]; - } - - if (x >= startPoint[0] && x <= startPoint[0] + size[0] && y >= startPoint[1] && y <= startPoint[1] + size[1]) { - return largeDataIndices[i]; - } - } - - return -1; - } - - function createBackgroundShape(isHorizontalOrRadial, layout, coord) { - if (isCoordinateSystemType(coord, 'cartesian2d')) { - var rectShape = layout; - var coordLayout = coord.getArea(); - return { - x: isHorizontalOrRadial ? rectShape.x : coordLayout.x, - y: isHorizontalOrRadial ? coordLayout.y : rectShape.y, - width: isHorizontalOrRadial ? rectShape.width : coordLayout.width, - height: isHorizontalOrRadial ? coordLayout.height : rectShape.height - }; - } else { - var coordLayout = coord.getArea(); - var sectorShape = layout; - return { - cx: coordLayout.cx, - cy: coordLayout.cy, - r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0, - r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r, - startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0, - endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2 - }; - } - } - - function createBackgroundEl(coord, isHorizontalOrRadial, layout) { - var ElementClz = coord.type === 'polar' ? Sector : Rect; - return new ElementClz({ - shape: createBackgroundShape(isHorizontalOrRadial, layout, coord), - silent: true, - z2: 0 - }); - } - - function install$9(registers) { - registers.registerChartView(BarView); - registers.registerSeriesModel(BarSeriesModel); - registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, curry$1(layout$1, 'bar')); // Do layout after other overall layout, which can prepare some information. - - registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, createProgressiveLayout('bar')); // Down sample after filter - - registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('bar')); - /** - * @payload - * @property {string} [componentType=series] - * @property {number} [dx] - * @property {number} [dy] - * @property {number} [zoom] - * @property {number} [originX] - * @property {number} [originY] - */ - - registers.registerAction({ - type: 'changeAxisOrder', - event: 'changeAxisOrder', - update: 'update' - }, function (payload, ecModel) { - var componentType = payload.componentType || 'series'; - ecModel.eachComponent({ - mainType: componentType, - query: payload - }, function (componentModel) { - if (payload.sortInfo) { - componentModel.axis.setCategorySortInfo(payload.sortInfo); - } - }); - }); - } - - use(install$9); - - var LineSeriesModel = - /** @class */ - function (_super) { - __extends(LineSeriesModel, _super); - - function LineSeriesModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = LineSeriesModel.type; - _this.hasSymbolVisual = true; - return _this; - } - - LineSeriesModel.prototype.getInitialData = function (option) { - { - var coordSys = option.coordinateSystem; - - if (coordSys !== 'polar' && coordSys !== 'cartesian2d') { - throw new Error('Line not support coordinateSystem besides cartesian and polar'); - } - } - return createSeriesData(null, this, { - useEncodeDefaulter: true - }); - }; - - LineSeriesModel.prototype.getLegendIcon = function (opt) { - var group = new Group$2(); - var line = createSymbol('line', 0, opt.itemHeight / 2, opt.itemWidth, 0, opt.lineStyle.stroke, false); - group.add(line); - line.setStyle(opt.lineStyle); - var visualType = this.getData().getVisual('symbol'); - var visualRotate = this.getData().getVisual('symbolRotate'); - var symbolType = visualType === 'none' ? 'circle' : visualType; // Symbol size is 80% when there is a line - - var size = opt.itemHeight * 0.8; - var symbol = createSymbol(symbolType, (opt.itemWidth - size) / 2, (opt.itemHeight - size) / 2, size, size, opt.itemStyle.fill); - group.add(symbol); - symbol.setStyle(opt.itemStyle); - var symbolRotate = opt.iconRotate === 'inherit' ? visualRotate : opt.iconRotate || 0; - symbol.rotation = symbolRotate * Math.PI / 180; - symbol.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]); - - if (symbolType.indexOf('empty') > -1) { - symbol.style.stroke = symbol.style.fill; - symbol.style.fill = '#fff'; - symbol.style.lineWidth = 2; - } - - return group; - }; - - LineSeriesModel.type = 'series.line'; - LineSeriesModel.dependencies = ['grid', 'polar']; - LineSeriesModel.defaultOption = { - // zlevel: 0, - z: 3, - coordinateSystem: 'cartesian2d', - legendHoverLink: true, - clip: true, - label: { - position: 'top' - }, - // itemStyle: { - // }, - endLabel: { - show: false, - valueAnimation: true, - distance: 8 - }, - lineStyle: { - width: 2, - type: 'solid' - }, - emphasis: { - scale: true - }, - // areaStyle: { - // origin of areaStyle. Valid values: - // `'auto'/null/undefined`: from axisLine to data - // `'start'`: from min to data - // `'end'`: from data to max - // origin: 'auto' - // }, - // false, 'start', 'end', 'middle' - step: false, - // Disabled if step is true - smooth: false, - smoothMonotone: null, - symbol: 'emptyCircle', - symbolSize: 4, - symbolRotate: null, - showSymbol: true, - // `false`: follow the label interval strategy. - // `true`: show all symbols. - // `'auto'`: If possible, show all symbols, otherwise - // follow the label interval strategy. - showAllSymbol: 'auto', - // Whether to connect break point. - connectNulls: false, - // Sampling for large data. Can be: 'average', 'max', 'min', 'sum', 'lttb'. - sampling: 'none', - animationEasing: 'linear', - // Disable progressive - progressive: 0, - hoverLayerThreshold: Infinity, - universalTransition: { - divideShape: 'clone' - }, - triggerLineEvent: false - }; - return LineSeriesModel; - }(SeriesModel); - - var Symbol = - /** @class */ - function (_super) { - __extends(Symbol, _super); - - function Symbol(data, idx, seriesScope, opts) { - var _this = _super.call(this) || this; - - _this.updateData(data, idx, seriesScope, opts); - - return _this; - } - - Symbol.prototype._createSymbol = function (symbolType, data, idx, symbolSize, keepAspect) { - // Remove paths created before - this.removeAll(); // let symbolPath = createSymbol( - // symbolType, -0.5, -0.5, 1, 1, color - // ); - // If width/height are set too small (e.g., set to 1) on ios10 - // and macOS Sierra, a circle stroke become a rect, no matter what - // the scale is set. So we set width/height as 2. See #4150. - - var symbolPath = createSymbol(symbolType, -1, -1, 2, 2, null, keepAspect); - symbolPath.attr({ - z2: 100, - culling: true, - scaleX: symbolSize[0] / 2, - scaleY: symbolSize[1] / 2 - }); // Rewrite drift method - - symbolPath.drift = driftSymbol; - this._symbolType = symbolType; - this.add(symbolPath); - }; - /** - * Stop animation - * @param {boolean} toLastFrame - */ - - - Symbol.prototype.stopSymbolAnimation = function (toLastFrame) { - this.childAt(0).stopAnimation(null, toLastFrame); - }; - - Symbol.prototype.getSymbolType = function () { - return this._symbolType; - }; - /** - * FIXME: - * Caution: This method breaks the encapsulation of this module, - * but it indeed brings convenience. So do not use the method - * unless you detailedly know all the implements of `Symbol`, - * especially animation. - * - * Get symbol path element. - */ - - - Symbol.prototype.getSymbolPath = function () { - return this.childAt(0); - }; - /** - * Highlight symbol - */ - - - Symbol.prototype.highlight = function () { - enterEmphasis(this.childAt(0)); - }; - /** - * Downplay symbol - */ - - - Symbol.prototype.downplay = function () { - leaveEmphasis(this.childAt(0)); - }; - /** - * @param {number} zlevel - * @param {number} z - */ - - - Symbol.prototype.setZ = function (zlevel, z) { - var symbolPath = this.childAt(0); - symbolPath.zlevel = zlevel; - symbolPath.z = z; - }; - - Symbol.prototype.setDraggable = function (draggable, hasCursorOption) { - var symbolPath = this.childAt(0); - symbolPath.draggable = draggable; - symbolPath.cursor = !hasCursorOption && draggable ? 'move' : symbolPath.cursor; - }; - /** - * Update symbol properties - */ - - - Symbol.prototype.updateData = function (data, idx, seriesScope, opts) { - this.silent = false; - var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; - var seriesModel = data.hostModel; - var symbolSize = Symbol.getSymbolSize(data, idx); - var isInit = symbolType !== this._symbolType; - var disableAnimation = opts && opts.disableAnimation; - - if (isInit) { - var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect'); - - this._createSymbol(symbolType, data, idx, symbolSize, keepAspect); - } else { - var symbolPath = this.childAt(0); - symbolPath.silent = false; - var target = { - scaleX: symbolSize[0] / 2, - scaleY: symbolSize[1] / 2 - }; - disableAnimation ? symbolPath.attr(target) : updateProps$1(symbolPath, target, seriesModel, idx); - saveOldStyle(symbolPath); - } - - this._updateCommon(data, idx, symbolSize, seriesScope, opts); - - if (isInit) { - var symbolPath = this.childAt(0); - - if (!disableAnimation) { - var target = { - scaleX: this._sizeX, - scaleY: this._sizeY, - style: { - // Always fadeIn. Because it has fadeOut animation when symbol is removed.. - opacity: symbolPath.style.opacity - } - }; - symbolPath.scaleX = symbolPath.scaleY = 0; - symbolPath.style.opacity = 0; - initProps(symbolPath, target, seriesModel, idx); - } - } - - if (disableAnimation) { - // Must stop leave transition manually if don't call initProps or updateProps. - this.childAt(0).stopAnimation('leave'); - } - }; - - Symbol.prototype._updateCommon = function (data, idx, symbolSize, seriesScope, opts) { - var symbolPath = this.childAt(0); - var seriesModel = data.hostModel; - var emphasisItemStyle; - var blurItemStyle; - var selectItemStyle; - var focus; - var blurScope; - var emphasisDisabled; - var labelStatesModels; - var hoverScale; - var cursorStyle; - - if (seriesScope) { - emphasisItemStyle = seriesScope.emphasisItemStyle; - blurItemStyle = seriesScope.blurItemStyle; - selectItemStyle = seriesScope.selectItemStyle; - focus = seriesScope.focus; - blurScope = seriesScope.blurScope; - labelStatesModels = seriesScope.labelStatesModels; - hoverScale = seriesScope.hoverScale; - cursorStyle = seriesScope.cursorStyle; - emphasisDisabled = seriesScope.emphasisDisabled; - } - - if (!seriesScope || data.hasItemOption) { - var itemModel = seriesScope && seriesScope.itemModel ? seriesScope.itemModel : data.getItemModel(idx); - var emphasisModel = itemModel.getModel('emphasis'); - emphasisItemStyle = emphasisModel.getModel('itemStyle').getItemStyle(); - selectItemStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); - blurItemStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); - focus = emphasisModel.get('focus'); - blurScope = emphasisModel.get('blurScope'); - emphasisDisabled = emphasisModel.get('disabled'); - labelStatesModels = getLabelStatesModels(itemModel); - hoverScale = emphasisModel.getShallow('scale'); - cursorStyle = itemModel.getShallow('cursor'); - } - - var symbolRotate = data.getItemVisual(idx, 'symbolRotate'); - symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); - var symbolOffset = normalizeSymbolOffset(data.getItemVisual(idx, 'symbolOffset'), symbolSize); - - if (symbolOffset) { - symbolPath.x = symbolOffset[0]; - symbolPath.y = symbolOffset[1]; - } - - cursorStyle && symbolPath.attr('cursor', cursorStyle); - var symbolStyle = data.getItemVisual(idx, 'style'); - var visualColor = symbolStyle.fill; - - if (symbolPath instanceof ZRImage) { - var pathStyle = symbolPath.style; - symbolPath.useStyle(extend({ - // TODO other properties like x, y ? - image: pathStyle.image, - x: pathStyle.x, - y: pathStyle.y, - width: pathStyle.width, - height: pathStyle.height - }, symbolStyle)); - } else { - if (symbolPath.__isEmptyBrush) { - // fill and stroke will be swapped if it's empty. - // So we cloned a new style to avoid it affecting the original style in visual storage. - // TODO Better implementation. No empty logic! - symbolPath.useStyle(extend({}, symbolStyle)); - } else { - symbolPath.useStyle(symbolStyle); - } // Disable decal because symbol scale will been applied on the decal. - - - symbolPath.style.decal = null; - symbolPath.setColor(visualColor, opts && opts.symbolInnerColor); - symbolPath.style.strokeNoScale = true; - } - - var liftZ = data.getItemVisual(idx, 'liftZ'); - var z2Origin = this._z2; - - if (liftZ != null) { - if (z2Origin == null) { - this._z2 = symbolPath.z2; - symbolPath.z2 += liftZ; - } - } else if (z2Origin != null) { - symbolPath.z2 = z2Origin; - this._z2 = null; - } - - var useNameLabel = opts && opts.useNameLabel; - setLabelStyle(symbolPath, labelStatesModels, { - labelFetcher: seriesModel, - labelDataIndex: idx, - defaultText: getLabelDefaultText, - inheritColor: visualColor, - defaultOpacity: symbolStyle.opacity - }); // Do not execute util needed. - - function getLabelDefaultText(idx) { - return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx); - } - - this._sizeX = symbolSize[0] / 2; - this._sizeY = symbolSize[1] / 2; - var emphasisState = symbolPath.ensureState('emphasis'); - emphasisState.style = emphasisItemStyle; - symbolPath.ensureState('select').style = selectItemStyle; - symbolPath.ensureState('blur').style = blurItemStyle; // null / undefined / true means to use default strategy. - // 0 / false / negative number / NaN / Infinity means no scale. - - var scaleRatio = hoverScale == null || hoverScale === true ? Math.max(1.1, 3 / this._sizeY) // PENDING: restrict hoverScale > 1? It seems unreasonable to scale down - : isFinite(hoverScale) && hoverScale > 0 ? +hoverScale : 1; // always set scale to allow resetting - - emphasisState.scaleX = this._sizeX * scaleRatio; - emphasisState.scaleY = this._sizeY * scaleRatio; - this.setSymbolScale(1); - toggleHoverEmphasis(this, focus, blurScope, emphasisDisabled); - }; - - Symbol.prototype.setSymbolScale = function (scale) { - this.scaleX = this.scaleY = scale; - }; - - Symbol.prototype.fadeOut = function (cb, seriesModel, opt) { - var symbolPath = this.childAt(0); - var dataIndex = getECData(this).dataIndex; - var animationOpt = opt && opt.animation; // Avoid mistaken hover when fading out - - this.silent = symbolPath.silent = true; // Not show text when animating - - if (opt && opt.fadeLabel) { - var textContent = symbolPath.getTextContent(); - - if (textContent) { - removeElement(textContent, { - style: { - opacity: 0 - } - }, seriesModel, { - dataIndex: dataIndex, - removeOpt: animationOpt, - cb: function () { - symbolPath.removeTextContent(); - } - }); - } - } else { - symbolPath.removeTextContent(); - } - - removeElement(symbolPath, { - style: { - opacity: 0 - }, - scaleX: 0, - scaleY: 0 - }, seriesModel, { - dataIndex: dataIndex, - cb: cb, - removeOpt: animationOpt - }); - }; - - Symbol.getSymbolSize = function (data, idx) { - return normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); - }; - - return Symbol; - }(Group$2); - - function driftSymbol(dx, dy) { - this.parent.drift(dx, dy); - } - - function symbolNeedsDraw(data, point, idx, opt) { - return point && !isNaN(point[0]) && !isNaN(point[1]) && !(opt.isIgnore && opt.isIgnore(idx)) // We do not set clipShape on group, because it will cut part of - // the symbol element shape. We use the same clip shape here as - // the line clip. - && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1])) && data.getItemVisual(idx, 'symbol') !== 'none'; - } - - function normalizeUpdateOpt(opt) { - if (opt != null && !isObject$2(opt)) { - opt = { - isIgnore: opt - }; - } - - return opt || {}; - } - - function makeSeriesScope(data) { - var seriesModel = data.hostModel; - var emphasisModel = seriesModel.getModel('emphasis'); - return { - emphasisItemStyle: emphasisModel.getModel('itemStyle').getItemStyle(), - blurItemStyle: seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(), - selectItemStyle: seriesModel.getModel(['select', 'itemStyle']).getItemStyle(), - focus: emphasisModel.get('focus'), - blurScope: emphasisModel.get('blurScope'), - emphasisDisabled: emphasisModel.get('disabled'), - hoverScale: emphasisModel.get('scale'), - labelStatesModels: getLabelStatesModels(seriesModel), - cursorStyle: seriesModel.get('cursor') - }; - } - - var SymbolDraw = - /** @class */ - function () { - function SymbolDraw(SymbolCtor) { - this.group = new Group$2(); - this._SymbolCtor = SymbolCtor || Symbol; - } - /** - * Update symbols draw by new data - */ - - - SymbolDraw.prototype.updateData = function (data, opt) { - // Remove progressive els. - this._progressiveEls = null; - opt = normalizeUpdateOpt(opt); - var group = this.group; - var seriesModel = data.hostModel; - var oldData = this._data; - var SymbolCtor = this._SymbolCtor; - var disableAnimation = opt.disableAnimation; - var seriesScope = makeSeriesScope(data); - var symbolUpdateOpt = { - disableAnimation: disableAnimation - }; - - var getSymbolPoint = opt.getSymbolPoint || function (idx) { - return data.getItemLayout(idx); - }; // There is no oldLineData only when first rendering or switching from - // stream mode to normal mode, where previous elements should be removed. - - - if (!oldData) { - group.removeAll(); - } - - data.diff(oldData).add(function (newIdx) { - var point = getSymbolPoint(newIdx); - - if (symbolNeedsDraw(data, point, newIdx, opt)) { - var symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt); - symbolEl.setPosition(point); - data.setItemGraphicEl(newIdx, symbolEl); - group.add(symbolEl); - } - }).update(function (newIdx, oldIdx) { - var symbolEl = oldData.getItemGraphicEl(oldIdx); - var point = getSymbolPoint(newIdx); - - if (!symbolNeedsDraw(data, point, newIdx, opt)) { - group.remove(symbolEl); - return; - } - - var newSymbolType = data.getItemVisual(newIdx, 'symbol') || 'circle'; - var oldSymbolType = symbolEl && symbolEl.getSymbolType && symbolEl.getSymbolType(); - - if (!symbolEl // Create a new if symbol type changed. - || oldSymbolType && oldSymbolType !== newSymbolType) { - group.remove(symbolEl); - symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt); - symbolEl.setPosition(point); - } else { - symbolEl.updateData(data, newIdx, seriesScope, symbolUpdateOpt); - var target = { - x: point[0], - y: point[1] - }; - disableAnimation ? symbolEl.attr(target) : updateProps$1(symbolEl, target, seriesModel); - } // Add back - - - group.add(symbolEl); - data.setItemGraphicEl(newIdx, symbolEl); - }).remove(function (oldIdx) { - var el = oldData.getItemGraphicEl(oldIdx); - el && el.fadeOut(function () { - group.remove(el); - }, seriesModel); - }).execute(); - this._getSymbolPoint = getSymbolPoint; - this._data = data; - }; - - SymbolDraw.prototype.updateLayout = function () { - var _this = this; - - var data = this._data; - - if (data) { - // Not use animation - data.eachItemGraphicEl(function (el, idx) { - var point = _this._getSymbolPoint(idx); - - el.setPosition(point); - el.markRedraw(); - }); - } - }; - - SymbolDraw.prototype.incrementalPrepareUpdate = function (data) { - this._seriesScope = makeSeriesScope(data); - this._data = null; - this.group.removeAll(); - }; - /** - * Update symbols draw by new data - */ - - - SymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) { - // Clear - this._progressiveEls = []; - opt = normalizeUpdateOpt(opt); - - function updateIncrementalAndHover(el) { - if (!el.isGroup) { - el.incremental = true; - el.ensureState('emphasis').hoverLayer = true; - } - } - - for (var idx = taskParams.start; idx < taskParams.end; idx++) { - var point = data.getItemLayout(idx); - - if (symbolNeedsDraw(data, point, idx, opt)) { - var el = new this._SymbolCtor(data, idx, this._seriesScope); - el.traverse(updateIncrementalAndHover); - el.setPosition(point); - this.group.add(el); - data.setItemGraphicEl(idx, el); - - this._progressiveEls.push(el); - } - } - }; - - SymbolDraw.prototype.eachRendered = function (cb) { - traverseElements(this._progressiveEls || this.group, cb); - }; - - SymbolDraw.prototype.remove = function (enableAnimation) { - var group = this.group; - var data = this._data; // Incremental model do not have this._data. - - if (data && enableAnimation) { - data.eachItemGraphicEl(function (el) { - el.fadeOut(function () { - group.remove(el); - }, data.hostModel); - }); - } else { - group.removeAll(); - } - }; - - return SymbolDraw; - }(); - - function prepareDataCoordInfo(coordSys, data, valueOrigin) { - var baseAxis = coordSys.getBaseAxis(); - var valueAxis = coordSys.getOtherAxis(baseAxis); - var valueStart = getValueStart(valueAxis, valueOrigin); - var baseAxisDim = baseAxis.dim; - var valueAxisDim = valueAxis.dim; - var valueDim = data.mapDimension(valueAxisDim); - var baseDim = data.mapDimension(baseAxisDim); - var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; - var dims = map$1(coordSys.dimensions, function (coordDim) { - return data.mapDimension(coordDim); - }); - var stacked = false; - var stackResultDim = data.getCalculationInfo('stackResultDimension'); - - if (isDimensionStacked(data, dims[0] - /* , dims[1] */ - )) { - // jshint ignore:line - stacked = true; - dims[0] = stackResultDim; - } - - if (isDimensionStacked(data, dims[1] - /* , dims[0] */ - )) { - // jshint ignore:line - stacked = true; - dims[1] = stackResultDim; - } - - return { - dataDimsForPoint: dims, - valueStart: valueStart, - valueAxisDim: valueAxisDim, - baseAxisDim: baseAxisDim, - stacked: !!stacked, - valueDim: valueDim, - baseDim: baseDim, - baseDataOffset: baseDataOffset, - stackedOverDimension: data.getCalculationInfo('stackedOverDimension') - }; - } - - function getValueStart(valueAxis, valueOrigin) { - var valueStart = 0; - var extent = valueAxis.scale.getExtent(); - - if (valueOrigin === 'start') { - valueStart = extent[0]; - } else if (valueOrigin === 'end') { - valueStart = extent[1]; - } // If origin is specified as a number, use it as - // valueStart directly - else if (isNumber(valueOrigin) && !isNaN(valueOrigin)) { - valueStart = valueOrigin; - } // auto - else { - // Both positive - if (extent[0] > 0) { - valueStart = extent[0]; - } // Both negative - else if (extent[1] < 0) { - valueStart = extent[1]; - } // If is one positive, and one negative, onZero shall be true - - } - - return valueStart; - } - - function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) { - var value = NaN; - - if (dataCoordInfo.stacked) { - value = data.get(data.getCalculationInfo('stackedOverDimension'), idx); - } - - if (isNaN(value)) { - value = dataCoordInfo.valueStart; - } - - var baseDataOffset = dataCoordInfo.baseDataOffset; - var stackedData = []; - stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx); - stackedData[1 - baseDataOffset] = value; - return coordSys.dataToPoint(stackedData); - } - - function diffData(oldData, newData) { - var diffResult = []; - newData.diff(oldData).add(function (idx) { - diffResult.push({ - cmd: '+', - idx: idx - }); - }).update(function (newIdx, oldIdx) { - diffResult.push({ - cmd: '=', - idx: oldIdx, - idx1: newIdx - }); - }).remove(function (idx) { - diffResult.push({ - cmd: '-', - idx: idx - }); - }).execute(); - return diffResult; - } - - function lineAnimationDiff(oldData, newData, oldStackedOnPoints, newStackedOnPoints, oldCoordSys, newCoordSys, oldValueOrigin, newValueOrigin) { - var diff = diffData(oldData, newData); // let newIdList = newData.mapArray(newData.getId); - // let oldIdList = oldData.mapArray(oldData.getId); - // convertToIntId(newIdList, oldIdList); - // // FIXME One data ? - // diff = arrayDiff(oldIdList, newIdList); - - var currPoints = []; - var nextPoints = []; // Points for stacking base line - - var currStackedPoints = []; - var nextStackedPoints = []; - var status = []; - var sortedIndices = []; - var rawIndices = []; - var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin); // const oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin); - - var oldPoints = oldData.getLayout('points') || []; - var newPoints = newData.getLayout('points') || []; - - for (var i = 0; i < diff.length; i++) { - var diffItem = diff[i]; - var pointAdded = true; - var oldIdx2 = void 0; - var newIdx2 = void 0; // FIXME, animation is not so perfect when dataZoom window moves fast - // Which is in case remvoing or add more than one data in the tail or head - - switch (diffItem.cmd) { - case '=': - oldIdx2 = diffItem.idx * 2; - newIdx2 = diffItem.idx1 * 2; - var currentX = oldPoints[oldIdx2]; - var currentY = oldPoints[oldIdx2 + 1]; - var nextX = newPoints[newIdx2]; - var nextY = newPoints[newIdx2 + 1]; // If previous data is NaN, use next point directly - - if (isNaN(currentX) || isNaN(currentY)) { - currentX = nextX; - currentY = nextY; - } - - currPoints.push(currentX, currentY); - nextPoints.push(nextX, nextY); - currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]); - nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); - rawIndices.push(newData.getRawIndex(diffItem.idx1)); - break; - - case '+': - var newIdx = diffItem.idx; - var newDataDimsForPoint = newDataOldCoordInfo.dataDimsForPoint; - var oldPt = oldCoordSys.dataToPoint([newData.get(newDataDimsForPoint[0], newIdx), newData.get(newDataDimsForPoint[1], newIdx)]); - newIdx2 = newIdx * 2; - currPoints.push(oldPt[0], oldPt[1]); - nextPoints.push(newPoints[newIdx2], newPoints[newIdx2 + 1]); - var stackedOnPoint = getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, newIdx); - currStackedPoints.push(stackedOnPoint[0], stackedOnPoint[1]); - nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); - rawIndices.push(newData.getRawIndex(newIdx)); - break; - - case '-': - pointAdded = false; - } // Original indices - - - if (pointAdded) { - status.push(diffItem); - sortedIndices.push(sortedIndices.length); - } - } // Diff result may be crossed if all items are changed - // Sort by data index - - - sortedIndices.sort(function (a, b) { - return rawIndices[a] - rawIndices[b]; - }); - var len = currPoints.length; - var sortedCurrPoints = createFloat32Array(len); - var sortedNextPoints = createFloat32Array(len); - var sortedCurrStackedPoints = createFloat32Array(len); - var sortedNextStackedPoints = createFloat32Array(len); - var sortedStatus = []; - - for (var i = 0; i < sortedIndices.length; i++) { - var idx = sortedIndices[i]; - var i2 = i * 2; - var idx2 = idx * 2; - sortedCurrPoints[i2] = currPoints[idx2]; - sortedCurrPoints[i2 + 1] = currPoints[idx2 + 1]; - sortedNextPoints[i2] = nextPoints[idx2]; - sortedNextPoints[i2 + 1] = nextPoints[idx2 + 1]; - sortedCurrStackedPoints[i2] = currStackedPoints[idx2]; - sortedCurrStackedPoints[i2 + 1] = currStackedPoints[idx2 + 1]; - sortedNextStackedPoints[i2] = nextStackedPoints[idx2]; - sortedNextStackedPoints[i2 + 1] = nextStackedPoints[idx2 + 1]; - sortedStatus[i] = status[idx]; - } - - return { - current: sortedCurrPoints, - next: sortedNextPoints, - stackedOnCurrent: sortedCurrStackedPoints, - stackedOnNext: sortedNextStackedPoints, - status: sortedStatus - }; - } - - var mathMin = Math.min; - var mathMax = Math.max; - - function isPointNull$1(x, y) { - return isNaN(x) || isNaN(y); - } - /** - * Draw smoothed line in non-monotone, in may cause undesired curve in extreme - * situations. This should be used when points are non-monotone neither in x or - * y dimension. - */ - - - function drawSegment(ctx, points, start, segLen, allLen, dir, smooth, smoothMonotone, connectNulls) { - var prevX; - var prevY; - var cpx0; - var cpy0; - var cpx1; - var cpy1; - var idx = start; - var k = 0; - - for (; k < segLen; k++) { - var x = points[idx * 2]; - var y = points[idx * 2 + 1]; - - if (idx >= allLen || idx < 0) { - break; - } - - if (isPointNull$1(x, y)) { - if (connectNulls) { - idx += dir; - continue; - } - - break; - } - - if (idx === start) { - ctx[dir > 0 ? 'moveTo' : 'lineTo'](x, y); - cpx0 = x; - cpy0 = y; - } else { - var dx = x - prevX; - var dy = y - prevY; // Ignore tiny segment. - - if (dx * dx + dy * dy < 0.5) { - idx += dir; - continue; - } - - if (smooth > 0) { - var nextIdx = idx + dir; - var nextX = points[nextIdx * 2]; - var nextY = points[nextIdx * 2 + 1]; // Ignore duplicate point - - while (nextX === x && nextY === y && k < segLen) { - k++; - nextIdx += dir; - idx += dir; - nextX = points[nextIdx * 2]; - nextY = points[nextIdx * 2 + 1]; - x = points[idx * 2]; - y = points[idx * 2 + 1]; - dx = x - prevX; - dy = y - prevY; - } - - var tmpK = k + 1; - - if (connectNulls) { - // Find next point not null - while (isPointNull$1(nextX, nextY) && tmpK < segLen) { - tmpK++; - nextIdx += dir; - nextX = points[nextIdx * 2]; - nextY = points[nextIdx * 2 + 1]; - } - } - - var ratioNextSeg = 0.5; - var vx = 0; - var vy = 0; - var nextCpx0 = void 0; - var nextCpy0 = void 0; // Is last point - - if (tmpK >= segLen || isPointNull$1(nextX, nextY)) { - cpx1 = x; - cpy1 = y; - } else { - vx = nextX - prevX; - vy = nextY - prevY; - var dx0 = x - prevX; - var dx1 = nextX - x; - var dy0 = y - prevY; - var dy1 = nextY - y; - var lenPrevSeg = void 0; - var lenNextSeg = void 0; - - if (smoothMonotone === 'x') { - lenPrevSeg = Math.abs(dx0); - lenNextSeg = Math.abs(dx1); - var dir_1 = vx > 0 ? 1 : -1; - cpx1 = x - dir_1 * lenPrevSeg * smooth; - cpy1 = y; - nextCpx0 = x + dir_1 * lenNextSeg * smooth; - nextCpy0 = y; - } else if (smoothMonotone === 'y') { - lenPrevSeg = Math.abs(dy0); - lenNextSeg = Math.abs(dy1); - var dir_2 = vy > 0 ? 1 : -1; - cpx1 = x; - cpy1 = y - dir_2 * lenPrevSeg * smooth; - nextCpx0 = x; - nextCpy0 = y + dir_2 * lenNextSeg * smooth; - } else { - lenPrevSeg = Math.sqrt(dx0 * dx0 + dy0 * dy0); - lenNextSeg = Math.sqrt(dx1 * dx1 + dy1 * dy1); // Use ratio of seg length - - ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg); - cpx1 = x - vx * smooth * (1 - ratioNextSeg); - cpy1 = y - vy * smooth * (1 - ratioNextSeg); // cp0 of next segment - - nextCpx0 = x + vx * smooth * ratioNextSeg; - nextCpy0 = y + vy * smooth * ratioNextSeg; // Smooth constraint between point and next point. - // Avoid exceeding extreme after smoothing. - - nextCpx0 = mathMin(nextCpx0, mathMax(nextX, x)); - nextCpy0 = mathMin(nextCpy0, mathMax(nextY, y)); - nextCpx0 = mathMax(nextCpx0, mathMin(nextX, x)); - nextCpy0 = mathMax(nextCpy0, mathMin(nextY, y)); // Reclaculate cp1 based on the adjusted cp0 of next seg. - - vx = nextCpx0 - x; - vy = nextCpy0 - y; - cpx1 = x - vx * lenPrevSeg / lenNextSeg; - cpy1 = y - vy * lenPrevSeg / lenNextSeg; // Smooth constraint between point and prev point. - // Avoid exceeding extreme after smoothing. - - cpx1 = mathMin(cpx1, mathMax(prevX, x)); - cpy1 = mathMin(cpy1, mathMax(prevY, y)); - cpx1 = mathMax(cpx1, mathMin(prevX, x)); - cpy1 = mathMax(cpy1, mathMin(prevY, y)); // Adjust next cp0 again. - - vx = x - cpx1; - vy = y - cpy1; - nextCpx0 = x + vx * lenNextSeg / lenPrevSeg; - nextCpy0 = y + vy * lenNextSeg / lenPrevSeg; - } - } - - ctx.bezierCurveTo(cpx0, cpy0, cpx1, cpy1, x, y); - cpx0 = nextCpx0; - cpy0 = nextCpy0; - } else { - ctx.lineTo(x, y); - } - } - - prevX = x; - prevY = y; - idx += dir; - } - - return k; - } - - var ECPolylineShape = - /** @class */ - function () { - function ECPolylineShape() { - this.smooth = 0; - this.smoothConstraint = true; - } - - return ECPolylineShape; - }(); - - var ECPolyline = - /** @class */ - function (_super) { - __extends(ECPolyline, _super); - - function ECPolyline(opts) { - var _this = _super.call(this, opts) || this; - - _this.type = 'ec-polyline'; - return _this; - } - - ECPolyline.prototype.getDefaultStyle = function () { - return { - stroke: '#000', - fill: null - }; - }; - - ECPolyline.prototype.getDefaultShape = function () { - return new ECPolylineShape(); - }; - - ECPolyline.prototype.buildPath = function (ctx, shape) { - var points = shape.points; - var i = 0; - var len = points.length / 2; // const result = getBoundingBox(points, shape.smoothConstraint); - - if (shape.connectNulls) { - // Must remove first and last null values avoid draw error in polygon - for (; len > 0; len--) { - if (!isPointNull$1(points[len * 2 - 2], points[len * 2 - 1])) { - break; - } - } - - for (; i < len; i++) { - if (!isPointNull$1(points[i * 2], points[i * 2 + 1])) { - break; - } - } - } - - while (i < len) { - i += drawSegment(ctx, points, i, len, len, 1, shape.smooth, shape.smoothMonotone, shape.connectNulls) + 1; - } - }; - - ECPolyline.prototype.getPointOn = function (xOrY, dim) { - if (!this.path) { - this.createPathProxy(); - this.buildPath(this.path, this.shape); - } - - var path = this.path; - var data = path.data; - var CMD = PathProxy.CMD; - var x0; - var y0; - var isDimX = dim === 'x'; - var roots = []; - - for (var i = 0; i < data.length;) { - var cmd = data[i++]; - var x = void 0; - var y = void 0; - var x2 = void 0; - var y2 = void 0; - var x3 = void 0; - var y3 = void 0; - var t = void 0; - - switch (cmd) { - case CMD.M: - x0 = data[i++]; - y0 = data[i++]; - break; - - case CMD.L: - x = data[i++]; - y = data[i++]; - t = isDimX ? (xOrY - x0) / (x - x0) : (xOrY - y0) / (y - y0); - - if (t <= 1 && t >= 0) { - var val = isDimX ? (y - y0) * t + y0 : (x - x0) * t + x0; - return isDimX ? [xOrY, val] : [val, xOrY]; - } - - x0 = x; - y0 = y; - break; - - case CMD.C: - x = data[i++]; - y = data[i++]; - x2 = data[i++]; - y2 = data[i++]; - x3 = data[i++]; - y3 = data[i++]; - var nRoot = isDimX ? cubicRootAt(x0, x, x2, x3, xOrY, roots) : cubicRootAt(y0, y, y2, y3, xOrY, roots); - - if (nRoot > 0) { - for (var i_1 = 0; i_1 < nRoot; i_1++) { - var t_1 = roots[i_1]; - - if (t_1 <= 1 && t_1 >= 0) { - var val = isDimX ? cubicAt(y0, y, y2, y3, t_1) : cubicAt(x0, x, x2, x3, t_1); - return isDimX ? [xOrY, val] : [val, xOrY]; - } - } - } - - x0 = x3; - y0 = y3; - break; - } - } - }; - - return ECPolyline; - }(Path); - - var ECPolygonShape = - /** @class */ - function (_super) { - __extends(ECPolygonShape, _super); - - function ECPolygonShape() { - return _super !== null && _super.apply(this, arguments) || this; - } - - return ECPolygonShape; - }(ECPolylineShape); - - var ECPolygon = - /** @class */ - function (_super) { - __extends(ECPolygon, _super); - - function ECPolygon(opts) { - var _this = _super.call(this, opts) || this; - - _this.type = 'ec-polygon'; - return _this; - } - - ECPolygon.prototype.getDefaultShape = function () { - return new ECPolygonShape(); - }; - - ECPolygon.prototype.buildPath = function (ctx, shape) { - var points = shape.points; - var stackedOnPoints = shape.stackedOnPoints; - var i = 0; - var len = points.length / 2; - var smoothMonotone = shape.smoothMonotone; - - if (shape.connectNulls) { - // Must remove first and last null values avoid draw error in polygon - for (; len > 0; len--) { - if (!isPointNull$1(points[len * 2 - 2], points[len * 2 - 1])) { - break; - } - } - - for (; i < len; i++) { - if (!isPointNull$1(points[i * 2], points[i * 2 + 1])) { - break; - } - } - } - - while (i < len) { - var k = drawSegment(ctx, points, i, len, len, 1, shape.smooth, smoothMonotone, shape.connectNulls); - drawSegment(ctx, stackedOnPoints, i + k - 1, k, len, -1, shape.stackedOnSmooth, smoothMonotone, shape.connectNulls); - i += k + 1; - ctx.closePath(); - } - }; - - return ECPolygon; - }(Path); - - function isPointsSame(points1, points2) { - if (points1.length !== points2.length) { - return; - } - - for (var i = 0; i < points1.length; i++) { - if (points1[i] !== points2[i]) { - return; - } - } - - return true; - } - - function bboxFromPoints(points) { - var minX = Infinity; - var minY = Infinity; - var maxX = -Infinity; - var maxY = -Infinity; - - for (var i = 0; i < points.length;) { - var x = points[i++]; - var y = points[i++]; - - if (!isNaN(x)) { - minX = Math.min(x, minX); - maxX = Math.max(x, maxX); - } - - if (!isNaN(y)) { - minY = Math.min(y, minY); - maxY = Math.max(y, maxY); - } - } - - return [[minX, minY], [maxX, maxY]]; - } - - function getBoundingDiff(points1, points2) { - var _a = bboxFromPoints(points1), - min1 = _a[0], - max1 = _a[1]; - - var _b = bboxFromPoints(points2), - min2 = _b[0], - max2 = _b[1]; // Get a max value from each corner of two boundings. - - - return Math.max(Math.abs(min1[0] - min2[0]), Math.abs(min1[1] - min2[1]), Math.abs(max1[0] - max2[0]), Math.abs(max1[1] - max2[1])); - } - - function getSmooth(smooth) { - return isNumber(smooth) ? smooth : smooth ? 0.5 : 0; - } - - function getStackedOnPoints(coordSys, data, dataCoordInfo) { - if (!dataCoordInfo.valueDim) { - return []; - } - - var len = data.count(); - var points = createFloat32Array(len * 2); - - for (var idx = 0; idx < len; idx++) { - var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx); - points[idx * 2] = pt[0]; - points[idx * 2 + 1] = pt[1]; - } - - return points; - } - - function turnPointsIntoStep(points, coordSys, stepTurnAt, connectNulls) { - var baseAxis = coordSys.getBaseAxis(); - var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; - var stepPoints = []; - var i = 0; - var stepPt = []; - var pt = []; - var nextPt = []; - var filteredPoints = []; - - if (connectNulls) { - for (i = 0; i < points.length; i += 2) { - if (!isNaN(points[i]) && !isNaN(points[i + 1])) { - filteredPoints.push(points[i], points[i + 1]); - } - } - - points = filteredPoints; - } - - for (i = 0; i < points.length - 2; i += 2) { - nextPt[0] = points[i + 2]; - nextPt[1] = points[i + 3]; - pt[0] = points[i]; - pt[1] = points[i + 1]; - stepPoints.push(pt[0], pt[1]); - - switch (stepTurnAt) { - case 'end': - stepPt[baseIndex] = nextPt[baseIndex]; - stepPt[1 - baseIndex] = pt[1 - baseIndex]; - stepPoints.push(stepPt[0], stepPt[1]); - break; - - case 'middle': - var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; - var stepPt2 = []; - stepPt[baseIndex] = stepPt2[baseIndex] = middle; - stepPt[1 - baseIndex] = pt[1 - baseIndex]; - stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; - stepPoints.push(stepPt[0], stepPt[1]); - stepPoints.push(stepPt2[0], stepPt2[1]); - break; - - default: - // default is start - stepPt[baseIndex] = pt[baseIndex]; - stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; - stepPoints.push(stepPt[0], stepPt[1]); - } - } // Last points - - - stepPoints.push(points[i++], points[i++]); - return stepPoints; - } - /** - * Clip color stops to edge. Avoid creating too large gradients. - * Which may lead to blurry when GPU acceleration is enabled. See #15680 - * - * The stops has been sorted from small to large. - */ - - - function clipColorStops(colorStops, maxSize) { - var newColorStops = []; - var len = colorStops.length; // coord will always < 0 in prevOutOfRangeColorStop. - - var prevOutOfRangeColorStop; - var prevInRangeColorStop; - - function lerpStop(stop0, stop1, clippedCoord) { - var coord0 = stop0.coord; - var p = (clippedCoord - coord0) / (stop1.coord - coord0); - var color = lerp(p, [stop0.color, stop1.color]); - return { - coord: clippedCoord, - color: color - }; - } - - for (var i = 0; i < len; i++) { - var stop_1 = colorStops[i]; - var coord = stop_1.coord; - - if (coord < 0) { - prevOutOfRangeColorStop = stop_1; - } else if (coord > maxSize) { - if (prevInRangeColorStop) { - newColorStops.push(lerpStop(prevInRangeColorStop, stop_1, maxSize)); - } else if (prevOutOfRangeColorStop) { - // If there are two stops and coord range is between these two stops - newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0), lerpStop(prevOutOfRangeColorStop, stop_1, maxSize)); - } // All following stop will be out of range. So just ignore them. - - - break; - } else { - if (prevOutOfRangeColorStop) { - newColorStops.push(lerpStop(prevOutOfRangeColorStop, stop_1, 0)); // Reset - - prevOutOfRangeColorStop = null; - } - - newColorStops.push(stop_1); - prevInRangeColorStop = stop_1; - } - } - - return newColorStops; - } - - function getVisualGradient(data, coordSys, api) { - var visualMetaList = data.getVisual('visualMeta'); - - if (!visualMetaList || !visualMetaList.length || !data.count()) { - // When data.count() is 0, gradient range can not be calculated. - return; - } - - if (coordSys.type !== 'cartesian2d') { - { - console.warn('Visual map on line style is only supported on cartesian2d.'); - } - return; - } - - var coordDim; - var visualMeta; - - for (var i = visualMetaList.length - 1; i >= 0; i--) { - var dimInfo = data.getDimensionInfo(visualMetaList[i].dimension); - coordDim = dimInfo && dimInfo.coordDim; // Can only be x or y - - if (coordDim === 'x' || coordDim === 'y') { - visualMeta = visualMetaList[i]; - break; - } - } - - if (!visualMeta) { - { - console.warn('Visual map on line style only support x or y dimension.'); - } - return; - } // If the area to be rendered is bigger than area defined by LinearGradient, - // the canvas spec prescribes that the color of the first stop and the last - // stop should be used. But if two stops are added at offset 0, in effect - // browsers use the color of the second stop to render area outside - // LinearGradient. So we can only infinitesimally extend area defined in - // LinearGradient to render `outerColors`. - - - var axis = coordSys.getAxis(coordDim); // dataToCoord mapping may not be linear, but must be monotonic. - - var colorStops = map$1(visualMeta.stops, function (stop) { - // offset will be calculated later. - return { - coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), - color: stop.color - }; - }); - var stopLen = colorStops.length; - var outerColors = visualMeta.outerColors.slice(); - - if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { - colorStops.reverse(); - outerColors.reverse(); - } - - var colorStopsInRange = clipColorStops(colorStops, coordDim === 'x' ? api.getWidth() : api.getHeight()); - var inRangeStopLen = colorStopsInRange.length; - - if (!inRangeStopLen && stopLen) { - // All stops are out of range. All will be the same color. - return colorStops[0].coord < 0 ? outerColors[1] ? outerColors[1] : colorStops[stopLen - 1].color : outerColors[0] ? outerColors[0] : colorStops[0].color; - } - - var tinyExtent = 10; // Arbitrary value: 10px - - var minCoord = colorStopsInRange[0].coord - tinyExtent; - var maxCoord = colorStopsInRange[inRangeStopLen - 1].coord + tinyExtent; - var coordSpan = maxCoord - minCoord; - - if (coordSpan < 1e-3) { - return 'transparent'; - } - - each$4(colorStopsInRange, function (stop) { - stop.offset = (stop.coord - minCoord) / coordSpan; - }); - colorStopsInRange.push({ - // NOTE: inRangeStopLen may still be 0 if stoplen is zero. - offset: inRangeStopLen ? colorStopsInRange[inRangeStopLen - 1].offset : 0.5, - color: outerColors[1] || 'transparent' - }); - colorStopsInRange.unshift({ - offset: inRangeStopLen ? colorStopsInRange[0].offset : 0.5, - color: outerColors[0] || 'transparent' - }); - var gradient = new LinearGradient(0, 0, 0, 0, colorStopsInRange, true); - gradient[coordDim] = minCoord; - gradient[coordDim + '2'] = maxCoord; - return gradient; - } - - function getIsIgnoreFunc(seriesModel, data, coordSys) { - var showAllSymbol = seriesModel.get('showAllSymbol'); - var isAuto = showAllSymbol === 'auto'; - - if (showAllSymbol && !isAuto) { - return; - } - - var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; - - if (!categoryAxis) { - return; - } // Note that category label interval strategy might bring some weird effect - // in some scenario: users may wonder why some of the symbols are not - // displayed. So we show all symbols as possible as we can. - - - if (isAuto // Simplify the logic, do not determine label overlap here. - && canShowAllSymbolForCategory(categoryAxis, data)) { - return; - } // Otherwise follow the label interval strategy on category axis. - - - var categoryDataDim = data.mapDimension(categoryAxis.dim); - var labelMap = {}; - each$4(categoryAxis.getViewLabels(), function (labelItem) { - var ordinalNumber = categoryAxis.scale.getRawOrdinalNumber(labelItem.tickValue); - labelMap[ordinalNumber] = 1; - }); - return function (dataIndex) { - return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex)); - }; - } - - function canShowAllSymbolForCategory(categoryAxis, data) { - // In most cases, line is monotonous on category axis, and the label size - // is close with each other. So we check the symbol size and some of the - // label size alone with the category axis to estimate whether all symbol - // can be shown without overlap. - var axisExtent = categoryAxis.getExtent(); - var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count(); - isNaN(availSize) && (availSize = 0); // 0/0 is NaN. - // Sampling some points, max 5. - - var dataLen = data.count(); - var step = Math.max(1, Math.round(dataLen / 5)); - - for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) { - if (Symbol.getSymbolSize(data, dataIndex // Only for cartesian, where `isHorizontal` exists. - )[categoryAxis.isHorizontal() ? 1 : 0] // Empirical number - * 1.5 > availSize) { - return false; - } - } - - return true; - } - - function isPointNull(x, y) { - return isNaN(x) || isNaN(y); - } - - function getLastIndexNotNull(points) { - var len = points.length / 2; - - for (; len > 0; len--) { - if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { - break; - } - } - - return len - 1; - } - - function getPointAtIndex(points, idx) { - return [points[idx * 2], points[idx * 2 + 1]]; - } - - function getIndexRange(points, xOrY, dim) { - var len = points.length / 2; - var dimIdx = dim === 'x' ? 0 : 1; - var a; - var b; - var prevIndex = 0; - var nextIndex = -1; - - for (var i = 0; i < len; i++) { - b = points[i * 2 + dimIdx]; - - if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) { - continue; - } - - if (i === 0) { - a = b; - continue; - } - - if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) { - nextIndex = i; - break; - } - - prevIndex = i; - a = b; - } - - return { - range: [prevIndex, nextIndex], - t: (xOrY - a) / (b - a) - }; - } - - function anyStateShowEndLabel(seriesModel) { - if (seriesModel.get(['endLabel', 'show'])) { - return true; - } - - for (var i = 0; i < SPECIAL_STATES.length; i++) { - if (seriesModel.get([SPECIAL_STATES[i], 'endLabel', 'show'])) { - return true; - } - } - - return false; - } - - function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) { - if (isCoordinateSystemType(coordSys, 'cartesian2d')) { - var endLabelModel_1 = seriesModel.getModel('endLabel'); - var valueAnimation_1 = endLabelModel_1.get('valueAnimation'); - var data_1 = seriesModel.getData(); - var labelAnimationRecord_1 = { - lastFrameIndex: 0 - }; - var during = anyStateShowEndLabel(seriesModel) ? function (percent, clipRect) { - lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys); - } : null; - var isHorizontal = coordSys.getBaseAxis().isHorizontal(); - var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () { - var endLabel = lineView._endLabel; - - if (endLabel && hasAnimation) { - if (labelAnimationRecord_1.originalX != null) { - endLabel.attr({ - x: labelAnimationRecord_1.originalX, - y: labelAnimationRecord_1.originalY - }); - } - } - }, during); // Expand clip shape to avoid clipping when line value exceeds axis - - if (!seriesModel.get('clip', true)) { - var rectShape = clipPath.shape; - var expandSize = Math.max(rectShape.width, rectShape.height); - - if (isHorizontal) { - rectShape.y -= expandSize; - rectShape.height += expandSize * 2; - } else { - rectShape.x -= expandSize; - rectShape.width += expandSize * 2; - } - } // Set to the final frame. To make sure label layout is right. - - - if (during) { - during(1, clipPath); - } - - return clipPath; - } else { - { - if (seriesModel.get(['endLabel', 'show'])) { - console.warn('endLabel is not supported for lines in polar systems.'); - } - } - return createPolarClipPath(coordSys, hasAnimation, seriesModel); - } - } - - function getEndLabelStateSpecified(endLabelModel, coordSys) { - var baseAxis = coordSys.getBaseAxis(); - var isHorizontal = baseAxis.isHorizontal(); - var isBaseInversed = baseAxis.inverse; - var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center'; - var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom'; - return { - normal: { - align: endLabelModel.get('align') || align, - verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign - } - }; - } - - var LineView = - /** @class */ - function (_super) { - __extends(LineView, _super); - - function LineView() { - return _super !== null && _super.apply(this, arguments) || this; - } - - LineView.prototype.init = function () { - var lineGroup = new Group$2(); - var symbolDraw = new SymbolDraw(); - this.group.add(symbolDraw.group); - this._symbolDraw = symbolDraw; - this._lineGroup = lineGroup; - }; - - LineView.prototype.render = function (seriesModel, ecModel, api) { - var _this = this; - - var coordSys = seriesModel.coordinateSystem; - var group = this.group; - var data = seriesModel.getData(); - var lineStyleModel = seriesModel.getModel('lineStyle'); - var areaStyleModel = seriesModel.getModel('areaStyle'); - var points = data.getLayout('points') || []; - var isCoordSysPolar = coordSys.type === 'polar'; - var prevCoordSys = this._coordSys; - var symbolDraw = this._symbolDraw; - var polyline = this._polyline; - var polygon = this._polygon; - var lineGroup = this._lineGroup; - var hasAnimation = !ecModel.ssr && seriesModel.get('animation'); - var isAreaChart = !areaStyleModel.isEmpty(); - var valueOrigin = areaStyleModel.get('origin'); - var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin); - var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo); - var showSymbol = seriesModel.get('showSymbol'); - var connectNulls = seriesModel.get('connectNulls'); - var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys); // Remove temporary symbols - - var oldData = this._data; - oldData && oldData.eachItemGraphicEl(function (el, idx) { - if (el.__temp) { - group.remove(el); - oldData.setItemGraphicEl(idx, null); - } - }); // Remove previous created symbols if showSymbol changed to false - - if (!showSymbol) { - symbolDraw.remove(); - } - - group.add(lineGroup); // FIXME step not support polar - - var step = !isCoordSysPolar ? seriesModel.get('step') : false; - var clipShapeForSymbol; - - if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) { - clipShapeForSymbol = coordSys.getArea(); // Avoid float number rounding error for symbol on the edge of axis extent. - // See #7913 and `test/dataZoom-clip.html`. - - if (clipShapeForSymbol.width != null) { - clipShapeForSymbol.x -= 0.1; - clipShapeForSymbol.y -= 0.1; - clipShapeForSymbol.width += 0.2; - clipShapeForSymbol.height += 0.2; - } else if (clipShapeForSymbol.r0) { - clipShapeForSymbol.r0 -= 0.5; - clipShapeForSymbol.r += 0.5; - } - } - - this._clipShapeForSymbol = clipShapeForSymbol; - var visualColor = getVisualGradient(data, coordSys, api) || data.getVisual('style')[data.getVisual('drawType')]; // Initialization animation or coordinate system changed - - if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) { - showSymbol && symbolDraw.updateData(data, { - isIgnore: isIgnoreFunc, - clipShape: clipShapeForSymbol, - disableAnimation: true, - getSymbolPoint: function (idx) { - return [points[idx * 2], points[idx * 2 + 1]]; - } - }); - hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol); - - if (step) { - // TODO If stacked series is not step - points = turnPointsIntoStep(points, coordSys, step, connectNulls); - - if (stackedOnPoints) { - stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step, connectNulls); - } - } - - polyline = this._newPolyline(points); - - if (isAreaChart) { - polygon = this._newPolygon(points, stackedOnPoints); - } // If areaStyle is removed - else if (polygon) { - lineGroup.remove(polygon); - polygon = this._polygon = null; - } // NOTE: Must update _endLabel before setClipPath. - - - if (!isCoordSysPolar) { - this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); - } - - lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); - } else { - if (isAreaChart && !polygon) { - // If areaStyle is added - polygon = this._newPolygon(points, stackedOnPoints); - } else if (polygon && !isAreaChart) { - // If areaStyle is removed - lineGroup.remove(polygon); - polygon = this._polygon = null; - } // NOTE: Must update _endLabel before setClipPath. - - - if (!isCoordSysPolar) { - this._initOrUpdateEndLabel(seriesModel, coordSys, convertToColorString(visualColor)); - } // Update clipPath - - - var oldClipPath = lineGroup.getClipPath(); - - if (oldClipPath) { - var newClipPath = createLineClipPath(this, coordSys, false, seriesModel); - initProps(oldClipPath, { - shape: newClipPath.shape - }, seriesModel); - } else { - lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); - } // Always update, or it is wrong in the case turning on legend - // because points are not changed. - - - showSymbol && symbolDraw.updateData(data, { - isIgnore: isIgnoreFunc, - clipShape: clipShapeForSymbol, - disableAnimation: true, - getSymbolPoint: function (idx) { - return [points[idx * 2], points[idx * 2 + 1]]; - } - }); // In the case data zoom triggered refreshing frequently - // Data may not change if line has a category axis. So it should animate nothing. - - if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) { - if (hasAnimation) { - this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls); - } else { - // Not do it in update with animation - if (step) { - // TODO If stacked series is not step - points = turnPointsIntoStep(points, coordSys, step, connectNulls); - - if (stackedOnPoints) { - stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step, connectNulls); - } - } - - polyline.setShape({ - points: points - }); - polygon && polygon.setShape({ - points: points, - stackedOnPoints: stackedOnPoints - }); - } - } - } - - var emphasisModel = seriesModel.getModel('emphasis'); - var focus = emphasisModel.get('focus'); - var blurScope = emphasisModel.get('blurScope'); - var emphasisDisabled = emphasisModel.get('disabled'); - polyline.useStyle(defaults( // Use color in lineStyle first - lineStyleModel.getLineStyle(), { - fill: 'none', - stroke: visualColor, - lineJoin: 'bevel' - })); - setStatesStylesFromModel(polyline, seriesModel, 'lineStyle'); - - if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') { - var emphasisLineStyle = polyline.getState('emphasis').style; - emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1; - } // Needs seriesIndex for focus - - - getECData(polyline).seriesIndex = seriesModel.seriesIndex; - toggleHoverEmphasis(polyline, focus, blurScope, emphasisDisabled); - var smooth = getSmooth(seriesModel.get('smooth')); - var smoothMonotone = seriesModel.get('smoothMonotone'); - polyline.setShape({ - smooth: smooth, - smoothMonotone: smoothMonotone, - connectNulls: connectNulls - }); - - if (polygon) { - var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); - var stackedOnSmooth = 0; - polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), { - fill: visualColor, - opacity: 0.7, - lineJoin: 'bevel', - decal: data.getVisual('style').decal - })); - - if (stackedOnSeries) { - stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); - } - - polygon.setShape({ - smooth: smooth, - stackedOnSmooth: stackedOnSmooth, - smoothMonotone: smoothMonotone, - connectNulls: connectNulls - }); - setStatesStylesFromModel(polygon, seriesModel, 'areaStyle'); // Needs seriesIndex for focus - - getECData(polygon).seriesIndex = seriesModel.seriesIndex; - toggleHoverEmphasis(polygon, focus, blurScope, emphasisDisabled); - } - - var changePolyState = function (toState) { - _this._changePolyState(toState); - }; - - data.eachItemGraphicEl(function (el) { - // Switch polyline / polygon state if element changed its state. - el && (el.onHoverStateChange = changePolyState); - }); - this._polyline.onHoverStateChange = changePolyState; - this._data = data; // Save the coordinate system for transition animation when data changed - - this._coordSys = coordSys; - this._stackedOnPoints = stackedOnPoints; - this._points = points; - this._step = step; - this._valueOrigin = valueOrigin; - - if (seriesModel.get('triggerLineEvent')) { - this.packEventData(seriesModel, polyline); - polygon && this.packEventData(seriesModel, polygon); - } - }; - - LineView.prototype.packEventData = function (seriesModel, el) { - getECData(el).eventData = { - componentType: 'series', - componentSubType: 'line', - componentIndex: seriesModel.componentIndex, - seriesIndex: seriesModel.seriesIndex, - seriesName: seriesModel.name, - seriesType: 'line' - }; - }; - - LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) { - var data = seriesModel.getData(); - var dataIndex = queryDataIndex(data, payload); - - this._changePolyState('emphasis'); - - if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { - var points = data.getLayout('points'); - var symbol = data.getItemGraphicEl(dataIndex); - - if (!symbol) { - // Create a temporary symbol if it is not exists - var x = points[dataIndex * 2]; - var y = points[dataIndex * 2 + 1]; - - if (isNaN(x) || isNaN(y)) { - // Null data - return; - } // fix #11360: shouldn't draw symbol outside clipShapeForSymbol - - - if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) { - return; - } - - var zlevel = seriesModel.get('zlevel') || 0; - var z = seriesModel.get('z') || 0; - symbol = new Symbol(data, dataIndex); - symbol.x = x; - symbol.y = y; - symbol.setZ(zlevel, z); // ensure label text of the temporary symbol is in front of line and area polygon - - var symbolLabel = symbol.getSymbolPath().getTextContent(); - - if (symbolLabel) { - symbolLabel.zlevel = zlevel; - symbolLabel.z = z; - symbolLabel.z2 = this._polyline.z2 + 1; - } - - symbol.__temp = true; - data.setItemGraphicEl(dataIndex, symbol); // Stop scale animation - - symbol.stopSymbolAnimation(true); - this.group.add(symbol); - } - - symbol.highlight(); - } else { - // Highlight whole series - ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload); - } - }; - - LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) { - var data = seriesModel.getData(); - var dataIndex = queryDataIndex(data, payload); - - this._changePolyState('normal'); - - if (dataIndex != null && dataIndex >= 0) { - var symbol = data.getItemGraphicEl(dataIndex); - - if (symbol) { - if (symbol.__temp) { - data.setItemGraphicEl(dataIndex, null); - this.group.remove(symbol); - } else { - symbol.downplay(); - } - } - } else { - // FIXME - // can not downplay completely. - // Downplay whole series - ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload); - } - }; - - LineView.prototype._changePolyState = function (toState) { - var polygon = this._polygon; - setStatesFlag(this._polyline, toState); - polygon && setStatesFlag(polygon, toState); - }; - - LineView.prototype._newPolyline = function (points) { - var polyline = this._polyline; // Remove previous created polyline - - if (polyline) { - this._lineGroup.remove(polyline); - } - - polyline = new ECPolyline({ - shape: { - points: points - }, - segmentIgnoreThreshold: 2, - z2: 10 - }); - - this._lineGroup.add(polyline); - - this._polyline = polyline; - return polyline; - }; - - LineView.prototype._newPolygon = function (points, stackedOnPoints) { - var polygon = this._polygon; // Remove previous created polygon - - if (polygon) { - this._lineGroup.remove(polygon); - } - - polygon = new ECPolygon({ - shape: { - points: points, - stackedOnPoints: stackedOnPoints - }, - segmentIgnoreThreshold: 2 - }); - - this._lineGroup.add(polygon); - - this._polygon = polygon; - return polygon; - }; - - LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) { - var isHorizontalOrRadial; - var isCoordSysPolar; - var baseAxis = coordSys.getBaseAxis(); - var isAxisInverse = baseAxis.inverse; - - if (coordSys.type === 'cartesian2d') { - isHorizontalOrRadial = baseAxis.isHorizontal(); - isCoordSysPolar = false; - } else if (coordSys.type === 'polar') { - isHorizontalOrRadial = baseAxis.dim === 'angle'; - isCoordSysPolar = true; - } - - var seriesModel = data.hostModel; - var seriesDuration = seriesModel.get('animationDuration'); - - if (isFunction(seriesDuration)) { - seriesDuration = seriesDuration(null); - } - - var seriesDelay = seriesModel.get('animationDelay') || 0; - var seriesDelayValue = isFunction(seriesDelay) ? seriesDelay(null) : seriesDelay; - data.eachItemGraphicEl(function (symbol, idx) { - var el = symbol; - - if (el) { - var point = [symbol.x, symbol.y]; - var start = void 0; - var end = void 0; - var current = void 0; - - if (clipShape) { - if (isCoordSysPolar) { - var polarClip = clipShape; - var coord = coordSys.pointToCoord(point); - - if (isHorizontalOrRadial) { - start = polarClip.startAngle; - end = polarClip.endAngle; - current = -coord[1] / 180 * Math.PI; - } else { - start = polarClip.r0; - end = polarClip.r; - current = coord[0]; - } - } else { - var gridClip = clipShape; - - if (isHorizontalOrRadial) { - start = gridClip.x; - end = gridClip.x + gridClip.width; - current = symbol.x; - } else { - start = gridClip.y + gridClip.height; - end = gridClip.y; - current = symbol.y; - } - } - } - - var ratio = end === start ? 0 : (current - start) / (end - start); - - if (isAxisInverse) { - ratio = 1 - ratio; - } - - var delay = isFunction(seriesDelay) ? seriesDelay(idx) : seriesDuration * ratio + seriesDelayValue; - var symbolPath = el.getSymbolPath(); - var text = symbolPath.getTextContent(); - el.attr({ - scaleX: 0, - scaleY: 0 - }); - el.animateTo({ - scaleX: 1, - scaleY: 1 - }, { - duration: 200, - setToFinal: true, - delay: delay - }); - - if (text) { - text.animateFrom({ - style: { - opacity: 0 - } - }, { - duration: 300, - delay: delay - }); - } - - symbolPath.disableLabelAnimation = true; - } - }); - }; - - LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys, inheritColor) { - var endLabelModel = seriesModel.getModel('endLabel'); - - if (anyStateShowEndLabel(seriesModel)) { - var data_2 = seriesModel.getData(); - var polyline = this._polyline; // series may be filtered. - - var points = data_2.getLayout('points'); - - if (!points) { - polyline.removeTextContent(); - this._endLabel = null; - return; - } - - var endLabel = this._endLabel; - - if (!endLabel) { - endLabel = this._endLabel = new ZRText({ - z2: 200 // should be higher than item symbol - - }); - endLabel.ignoreClip = true; - polyline.setTextContent(this._endLabel); - polyline.disableLabelAnimation = true; - } // Find last non-NaN data to display data - - - var dataIndex = getLastIndexNotNull(points); - - if (dataIndex >= 0) { - setLabelStyle(polyline, getLabelStatesModels(seriesModel, 'endLabel'), { - inheritColor: inheritColor, - labelFetcher: seriesModel, - labelDataIndex: dataIndex, - defaultText: function (dataIndex, opt, interpolatedValue) { - return interpolatedValue != null ? getDefaultInterpolatedLabel(data_2, interpolatedValue) : getDefaultLabel(data_2, dataIndex); - }, - enableTextSetter: true - }, getEndLabelStateSpecified(endLabelModel, coordSys)); - polyline.textConfig.position = null; - } - } else if (this._endLabel) { - this._polyline.removeTextContent(); - - this._endLabel = null; - } - }; - - LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) { - var endLabel = this._endLabel; - var polyline = this._polyline; - - if (endLabel) { - // NOTE: Don't remove percent < 1. percent === 1 means the first frame during render. - // The label is not prepared at this time. - if (percent < 1 && animationRecord.originalX == null) { - animationRecord.originalX = endLabel.x; - animationRecord.originalY = endLabel.y; - } - - var points = data.getLayout('points'); - var seriesModel = data.hostModel; - var connectNulls = seriesModel.get('connectNulls'); - var precision = endLabelModel.get('precision'); - var distance = endLabelModel.get('distance') || 0; - var baseAxis = coordSys.getBaseAxis(); - var isHorizontal = baseAxis.isHorizontal(); - var isBaseInversed = baseAxis.inverse; - var clipShape = clipRect.shape; - var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y; - var distanceX = (isHorizontal ? distance : 0) * (isBaseInversed ? -1 : 1); - var distanceY = (isHorizontal ? 0 : -distance) * (isBaseInversed ? -1 : 1); - var dim = isHorizontal ? 'x' : 'y'; - var dataIndexRange = getIndexRange(points, xOrY, dim); - var indices = dataIndexRange.range; - var diff = indices[1] - indices[0]; - var value = void 0; - - if (diff >= 1) { - // diff > 1 && connectNulls, which is on the null data. - if (diff > 1 && !connectNulls) { - var pt = getPointAtIndex(points, indices[0]); - endLabel.attr({ - x: pt[0] + distanceX, - y: pt[1] + distanceY - }); - valueAnimation && (value = seriesModel.getRawValue(indices[0])); - } else { - var pt = polyline.getPointOn(xOrY, dim); - pt && endLabel.attr({ - x: pt[0] + distanceX, - y: pt[1] + distanceY - }); - var startValue = seriesModel.getRawValue(indices[0]); - var endValue = seriesModel.getRawValue(indices[1]); - valueAnimation && (value = interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t)); - } - - animationRecord.lastFrameIndex = indices[0]; - } else { - // If diff <= 0, which is the range is not found(Include NaN) - // Choose the first point or last point. - var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0; - var pt = getPointAtIndex(points, idx); - valueAnimation && (value = seriesModel.getRawValue(idx)); - endLabel.attr({ - x: pt[0] + distanceX, - y: pt[1] + distanceY - }); - } - - if (valueAnimation) { - var inner = labelInner(endLabel); - - if (typeof inner.setLabelText === 'function') { - inner.setLabelText(value); - } - } - } - }; - /** - * @private - */ - // FIXME Two value axis - - - LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin, connectNulls) { - var polyline = this._polyline; - var polygon = this._polygon; - var seriesModel = data.hostModel; - var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin); - var current = diff.current; - var stackedOnCurrent = diff.stackedOnCurrent; - var next = diff.next; - var stackedOnNext = diff.stackedOnNext; - - if (step) { - // TODO If stacked series is not step - current = turnPointsIntoStep(diff.current, coordSys, step, connectNulls); - stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step, connectNulls); - next = turnPointsIntoStep(diff.next, coordSys, step, connectNulls); - stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step, connectNulls); - } // Don't apply animation if diff is large. - // For better result and avoid memory explosion problems like - // https://github.com/apache/incubator-echarts/issues/12229 - - - if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) { - polyline.stopAnimation(); - polyline.setShape({ - points: next - }); - - if (polygon) { - polygon.stopAnimation(); - polygon.setShape({ - points: next, - stackedOnPoints: stackedOnNext - }); - } - - return; - } - - polyline.shape.__points = diff.current; - polyline.shape.points = current; - var target = { - shape: { - points: next - } - }; // Also animate the original points. - // If points reference is changed when turning into step line. - - if (diff.current !== current) { - target.shape.__points = diff.next; - } // Stop previous animation. - - - polyline.stopAnimation(); - updateProps$1(polyline, target, seriesModel); - - if (polygon) { - polygon.setShape({ - // Reuse the points with polyline. - points: current, - stackedOnPoints: stackedOnCurrent - }); - polygon.stopAnimation(); - updateProps$1(polygon, { - shape: { - stackedOnPoints: stackedOnNext - } - }, seriesModel); // If use attr directly in updateProps. - - if (polyline.shape.points !== polygon.shape.points) { - polygon.shape.points = polyline.shape.points; - } - } - - var updatedDataInfo = []; - var diffStatus = diff.status; - - for (var i = 0; i < diffStatus.length; i++) { - var cmd = diffStatus[i].cmd; - - if (cmd === '=') { - var el = data.getItemGraphicEl(diffStatus[i].idx1); - - if (el) { - updatedDataInfo.push({ - el: el, - ptIdx: i // Index of points - - }); - } - } - } - - if (polyline.animators && polyline.animators.length) { - polyline.animators[0].during(function () { - polygon && polygon.dirtyShape(); - var points = polyline.shape.__points; - - for (var i = 0; i < updatedDataInfo.length; i++) { - var el = updatedDataInfo[i].el; - var offset = updatedDataInfo[i].ptIdx * 2; - el.x = points[offset]; - el.y = points[offset + 1]; - el.markRedraw(); - } - }); - } - }; - - LineView.prototype.remove = function (ecModel) { - var group = this.group; - var oldData = this._data; - - this._lineGroup.removeAll(); - - this._symbolDraw.remove(true); // Remove temporary created elements when highlighting - - - oldData && oldData.eachItemGraphicEl(function (el, idx) { - if (el.__temp) { - group.remove(el); - oldData.setItemGraphicEl(idx, null); - } - }); - this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null; - }; - - LineView.type = 'line'; - return LineView; - }(ChartView); - - function pointsLayout(seriesType, forceStoreInTypedArray) { - return { - seriesType: seriesType, - plan: createRenderPlanner(), - reset: function (seriesModel) { - var data = seriesModel.getData(); - var coordSys = seriesModel.coordinateSystem; - var pipelineContext = seriesModel.pipelineContext; - var useTypedArray = forceStoreInTypedArray || pipelineContext.large; - - if (!coordSys) { - return; - } - - var dims = map$1(coordSys.dimensions, function (dim) { - return data.mapDimension(dim); - }).slice(0, 2); - var dimLen = dims.length; - var stackResultDim = data.getCalculationInfo('stackResultDimension'); - - if (isDimensionStacked(data, dims[0])) { - dims[0] = stackResultDim; - } - - if (isDimensionStacked(data, dims[1])) { - dims[1] = stackResultDim; - } - - var store = data.getStore(); - var dimIdx0 = data.getDimensionIndex(dims[0]); - var dimIdx1 = data.getDimensionIndex(dims[1]); - return dimLen && { - progress: function (params, data) { - var segCount = params.end - params.start; - var points = useTypedArray && createFloat32Array(segCount * dimLen); - var tmpIn = []; - var tmpOut = []; - - for (var i = params.start, offset = 0; i < params.end; i++) { - var point = void 0; - - if (dimLen === 1) { - var x = store.get(dimIdx0, i); // NOTE: Make sure the second parameter is null to use default strategy. - - point = coordSys.dataToPoint(x, null, tmpOut); - } else { - tmpIn[0] = store.get(dimIdx0, i); - tmpIn[1] = store.get(dimIdx1, i); // Let coordinate system to handle the NaN data. - - point = coordSys.dataToPoint(tmpIn, null, tmpOut); - } - - if (useTypedArray) { - points[offset++] = point[0]; - points[offset++] = point[1]; - } else { - data.setItemLayout(i, point.slice()); - } - } - - useTypedArray && data.setLayout('points', points); - } - }; - } - }; - } - - function install$8(registers) { - registers.registerChartView(LineView); - registers.registerSeriesModel(LineSeriesModel); - registers.registerLayout(pointsLayout('line', true)); - registers.registerVisual({ - seriesType: 'line', - reset: function (seriesModel) { - var data = seriesModel.getData(); // Visual coding for legend - - var lineStyle = seriesModel.getModel('lineStyle').getLineStyle(); - - if (lineStyle && !lineStyle.stroke) { - // Fill in visual should be palette color if - // has color callback - lineStyle.stroke = data.getVisual('style').fill; - } - - data.setVisual('legendLineStyle', lineStyle); - } - }); // Down sample after filter - - registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('line')); - } - - use(install$8); - var PI2$1 = Math.PI * 2; - var RADIAN$1 = Math.PI / 180; - - function getViewRect(seriesModel, api) { - return getLayoutRect(seriesModel.getBoxLayoutParams(), { - width: api.getWidth(), - height: api.getHeight() - }); - } - - function getBasicPieLayout(seriesModel, api) { - var viewRect = getViewRect(seriesModel, api); // center can be string or number when coordinateSystem is specified - - var center = seriesModel.get('center'); - var radius = seriesModel.get('radius'); - - if (!isArray(radius)) { - radius = [0, radius]; - } - - var width = parsePercent(viewRect.width, api.getWidth()); - var height = parsePercent(viewRect.height, api.getHeight()); - var size = Math.min(width, height); - var r0 = parsePercent(radius[0], size / 2); - var r = parsePercent(radius[1], size / 2); - var cx; - var cy; - var coordSys = seriesModel.coordinateSystem; - - if (coordSys) { - // percentage is not allowed when coordinate system is specified - var point = coordSys.dataToPoint(center); - cx = point[0] || 0; - cy = point[1] || 0; - } else { - if (!isArray(center)) { - center = [center, center]; - } - - cx = parsePercent(center[0], width) + viewRect.x; - cy = parsePercent(center[1], height) + viewRect.y; - } - - return { - cx: cx, - cy: cy, - r0: r0, - r: r - }; - } - - function pieLayout(seriesType, ecModel, api) { - ecModel.eachSeriesByType(seriesType, function (seriesModel) { - var data = seriesModel.getData(); - var valueDim = data.mapDimension('value'); - var viewRect = getViewRect(seriesModel, api); - - var _a = getBasicPieLayout(seriesModel, api), - cx = _a.cx, - cy = _a.cy, - r = _a.r, - r0 = _a.r0; - - var startAngle = -seriesModel.get('startAngle') * RADIAN$1; - var endAngle = seriesModel.get('endAngle'); - var padAngle = seriesModel.get('padAngle') * RADIAN$1; - endAngle = endAngle === 'auto' ? startAngle - PI2$1 : -endAngle * RADIAN$1; - var minAngle = seriesModel.get('minAngle') * RADIAN$1; - var minAndPadAngle = minAngle + padAngle; - var validDataCount = 0; - data.each(valueDim, function (value) { - !isNaN(value) && validDataCount++; - }); - var sum = data.getSum(valueDim); // Sum may be 0 - - var unitRadian = Math.PI / (sum || validDataCount) * 2; - var clockwise = seriesModel.get('clockwise'); - var roseType = seriesModel.get('roseType'); - var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); // [0...max] - - var extent = data.getDataExtent(valueDim); - extent[0] = 0; - var dir = clockwise ? 1 : -1; - var angles = [startAngle, endAngle]; - var halfPadAngle = dir * padAngle / 2; - normalizeArcAngles(angles, !clockwise); - startAngle = angles[0], endAngle = angles[1]; - var angleRange = Math.abs(endAngle - startAngle); // In the case some sector angle is smaller than minAngle - - var restAngle = angleRange; - var valueSumLargerThanMinAngle = 0; - var currentAngle = startAngle; - data.setLayout({ - viewRect: viewRect, - r: r - }); - data.each(valueDim, function (value, idx) { - var angle; - - if (isNaN(value)) { - data.setItemLayout(idx, { - angle: NaN, - startAngle: NaN, - endAngle: NaN, - clockwise: clockwise, - cx: cx, - cy: cy, - r0: r0, - r: roseType ? NaN : r - }); - return; - } // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样? - - - if (roseType !== 'area') { - angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian; - } else { - angle = angleRange / validDataCount; - } - - if (angle < minAndPadAngle) { - angle = minAndPadAngle; - restAngle -= minAndPadAngle; - } else { - valueSumLargerThanMinAngle += value; - } - - var endAngle = currentAngle + dir * angle; // calculate display angle - - var actualStartAngle = 0; - var actualEndAngle = 0; - - if (padAngle > angle) { - actualStartAngle = currentAngle + dir * angle / 2; - actualEndAngle = actualStartAngle; - } else { - actualStartAngle = currentAngle + halfPadAngle; - actualEndAngle = endAngle - halfPadAngle; - } - - data.setItemLayout(idx, { - angle: angle, - startAngle: actualStartAngle, - endAngle: actualEndAngle, - clockwise: clockwise, - cx: cx, - cy: cy, - r0: r0, - r: roseType ? linearMap(value, extent, [r0, r]) : r - }); - currentAngle = endAngle; - }); // Some sector is constrained by minAngle and padAngle - // Rest sectors needs recalculate angle - - if (restAngle < PI2$1 && validDataCount) { - // Average the angle if rest angle is not enough after all angles is - // Constrained by minAngle and padAngle - if (restAngle <= 1e-3) { - var angle_1 = angleRange / validDataCount; - data.each(valueDim, function (value, idx) { - if (!isNaN(value)) { - var layout_1 = data.getItemLayout(idx); - layout_1.angle = angle_1; - var actualStartAngle = 0; - var actualEndAngle = 0; - - if (angle_1 < padAngle) { - actualStartAngle = startAngle + dir * (idx + 1 / 2) * angle_1; - actualEndAngle = actualStartAngle; - } else { - actualStartAngle = startAngle + dir * idx * angle_1 + halfPadAngle; - actualEndAngle = startAngle + dir * (idx + 1) * angle_1 - halfPadAngle; - } - - layout_1.startAngle = actualStartAngle; - layout_1.endAngle = actualEndAngle; - } - }); - } else { - unitRadian = restAngle / valueSumLargerThanMinAngle; - currentAngle = startAngle; - data.each(valueDim, function (value, idx) { - if (!isNaN(value)) { - var layout_2 = data.getItemLayout(idx); - var angle = layout_2.angle === minAndPadAngle ? minAndPadAngle : value * unitRadian; - var actualStartAngle = 0; - var actualEndAngle = 0; - - if (angle < padAngle) { - actualStartAngle = currentAngle + dir * angle / 2; - actualEndAngle = actualStartAngle; - } else { - actualStartAngle = currentAngle + halfPadAngle; - actualEndAngle = currentAngle + dir * angle - halfPadAngle; - } - - layout_2.startAngle = actualStartAngle; - layout_2.endAngle = actualEndAngle; - currentAngle += dir * angle; - } - }); - } - } - }); - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - function dataFilter(seriesType) { - return { - seriesType: seriesType, - reset: function (seriesModel, ecModel) { - var legendModels = ecModel.findComponents({ - mainType: 'legend' - }); - - if (!legendModels || !legendModels.length) { - return; - } - - var data = seriesModel.getData(); - data.filterSelf(function (idx) { - var name = data.getName(idx); // If in any legend component the status is not selected. - - for (var i = 0; i < legendModels.length; i++) { - // @ts-ignore FIXME: LegendModel - if (!legendModels[i].isSelected(name)) { - return false; - } - } - - return true; - }); - } - }; - } - - var RADIAN = Math.PI / 180; - - function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) { - if (list.length < 2) { - return; - } - - function recalculateXOnSemiToAlignOnEllipseCurve(semi) { - var rB = semi.rB; - var rB2 = rB * rB; - - for (var i = 0; i < semi.list.length; i++) { - var item = semi.list[i]; - var dy = Math.abs(item.label.y - cy); // horizontal r is always same with original r because x is not changed. - - var rA = r + item.len; - var rA2 = rA * rA; // Use ellipse implicit function to calculate x - - var dx = Math.sqrt((1 - Math.abs(dy * dy / rB2)) * rA2); - var newX = cx + (dx + item.len2) * dir; - var deltaX = newX - item.label.x; - var newTargetWidth = item.targetTextWidth - deltaX * dir; // text x is changed, so need to recalculate width. - - constrainTextWidth(item, newTargetWidth, true); - item.label.x = newX; - } - } // Adjust X based on the shifted y. Make tight labels aligned on an ellipse curve. - - - function recalculateX(items) { - // Extremes of - var topSemi = { - list: [], - maxY: 0 - }; - var bottomSemi = { - list: [], - maxY: 0 - }; - - for (var i = 0; i < items.length; i++) { - if (items[i].labelAlignTo !== 'none') { - continue; - } - - var item = items[i]; - var semi = item.label.y > cy ? bottomSemi : topSemi; - var dy = Math.abs(item.label.y - cy); - - if (dy >= semi.maxY) { - var dx = item.label.x - cx - item.len2 * dir; // horizontal r is always same with original r because x is not changed. - - var rA = r + item.len; // Canculate rB based on the topest / bottemest label. - - var rB = Math.abs(dx) < rA ? Math.sqrt(dy * dy / (1 - dx * dx / rA / rA)) : rA; - semi.rB = rB; - semi.maxY = dy; - } - - semi.list.push(item); - } - - recalculateXOnSemiToAlignOnEllipseCurve(topSemi); - recalculateXOnSemiToAlignOnEllipseCurve(bottomSemi); - } - - var len = list.length; - - for (var i = 0; i < len; i++) { - if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') { - var dx = list[i].label.x - farthestX; - list[i].linePoints[1][0] += dx; - list[i].label.x = farthestX; - } - } - - if (shiftLayoutOnY(list, viewTop, viewTop + viewHeight)) { - recalculateX(list); - } - } - - function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) { - var leftList = []; - var rightList = []; - var leftmostX = Number.MAX_VALUE; - var rightmostX = -Number.MAX_VALUE; - - for (var i = 0; i < labelLayoutList.length; i++) { - var label = labelLayoutList[i].label; - - if (isPositionCenter(labelLayoutList[i])) { - continue; - } - - if (label.x < cx) { - leftmostX = Math.min(leftmostX, label.x); - leftList.push(labelLayoutList[i]); - } else { - rightmostX = Math.max(rightmostX, label.x); - rightList.push(labelLayoutList[i]); - } - } - - for (var i = 0; i < labelLayoutList.length; i++) { - var layout = labelLayoutList[i]; - - if (!isPositionCenter(layout) && layout.linePoints) { - if (layout.labelStyleWidth != null) { - continue; - } - - var label = layout.label; - var linePoints = layout.linePoints; - var targetTextWidth = void 0; - - if (layout.labelAlignTo === 'edge') { - if (label.x < cx) { - targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.edgeDistance; - } else { - targetTextWidth = viewLeft + viewWidth - layout.edgeDistance - linePoints[2][0] - layout.labelDistance; - } - } else if (layout.labelAlignTo === 'labelLine') { - if (label.x < cx) { - targetTextWidth = leftmostX - viewLeft - layout.bleedMargin; - } else { - targetTextWidth = viewLeft + viewWidth - rightmostX - layout.bleedMargin; - } - } else { - if (label.x < cx) { - targetTextWidth = label.x - viewLeft - layout.bleedMargin; - } else { - targetTextWidth = viewLeft + viewWidth - label.x - layout.bleedMargin; - } - } - - layout.targetTextWidth = targetTextWidth; - constrainTextWidth(layout, targetTextWidth); - } - } - - adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX); - adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX); - - for (var i = 0; i < labelLayoutList.length; i++) { - var layout = labelLayoutList[i]; - - if (!isPositionCenter(layout) && layout.linePoints) { - var label = layout.label; - var linePoints = layout.linePoints; - var isAlignToEdge = layout.labelAlignTo === 'edge'; - var padding = label.style.padding; - var paddingH = padding ? padding[1] + padding[3] : 0; // textRect.width already contains paddingH if bgColor is set - - var extraPaddingH = label.style.backgroundColor ? 0 : paddingH; - var realTextWidth = layout.rect.width + extraPaddingH; - var dist = linePoints[1][0] - linePoints[2][0]; - - if (isAlignToEdge) { - if (label.x < cx) { - linePoints[2][0] = viewLeft + layout.edgeDistance + realTextWidth + layout.labelDistance; - } else { - linePoints[2][0] = viewLeft + viewWidth - layout.edgeDistance - realTextWidth - layout.labelDistance; - } - } else { - if (label.x < cx) { - linePoints[2][0] = label.x + layout.labelDistance; - } else { - linePoints[2][0] = label.x - layout.labelDistance; - } - - linePoints[1][0] = linePoints[2][0] + dist; - } - - linePoints[1][1] = linePoints[2][1] = label.y; - } - } - } - /** - * Set max width of each label, and then wrap each label to the max width. - * - * @param layout label layout - * @param availableWidth max width for the label to display - * @param forceRecalculate recaculate the text layout even if the current width - * is smaller than `availableWidth`. This is useful when the text was previously - * wrapped by calling `constrainTextWidth` but now `availableWidth` changed, in - * which case, previous wrapping should be redo. - */ - - - function constrainTextWidth(layout, availableWidth, forceRecalculate) { - if (forceRecalculate === void 0) { - forceRecalculate = false; - } - - if (layout.labelStyleWidth != null) { - // User-defined style.width has the highest priority. - return; - } - - var label = layout.label; - var style = label.style; - var textRect = layout.rect; - var bgColor = style.backgroundColor; - var padding = style.padding; - var paddingH = padding ? padding[1] + padding[3] : 0; - var overflow = style.overflow; // textRect.width already contains paddingH if bgColor is set - - var oldOuterWidth = textRect.width + (bgColor ? 0 : paddingH); - - if (availableWidth < oldOuterWidth || forceRecalculate) { - var oldHeight = textRect.height; - - if (overflow && overflow.match('break')) { - // Temporarily set background to be null to calculate - // the bounding box without background. - label.setStyle('backgroundColor', null); // Set constraining width - - label.setStyle('width', availableWidth - paddingH); // This is the real bounding box of the text without padding. - - var innerRect = label.getBoundingRect(); - label.setStyle('width', Math.ceil(innerRect.width)); - label.setStyle('backgroundColor', bgColor); - } else { - var availableInnerWidth = availableWidth - paddingH; - var newWidth = availableWidth < oldOuterWidth // Current text is too wide, use `availableWidth` as max width. - ? availableInnerWidth : // Current available width is enough, but the text may have - // already been wrapped with a smaller available width. - forceRecalculate ? availableInnerWidth > layout.unconstrainedWidth // Current available is larger than text width, - // so don't constrain width (otherwise it may have - // empty space in the background). - ? null // Current available is smaller than text width, so - // use the current available width as constraining - // width. - : availableInnerWidth // Current available width is enough, so no need to - // constrain. - : null; - label.setStyle('width', newWidth); - } - - var newRect = label.getBoundingRect(); - textRect.width = newRect.width; - var margin = (label.style.margin || 0) + 2.1; - textRect.height = newRect.height + margin; - textRect.y -= (textRect.height - oldHeight) / 2; - } - } - - function isPositionCenter(sectorShape) { - // Not change x for center label - return sectorShape.position === 'center'; - } - - function pieLabelLayout(seriesModel) { - var data = seriesModel.getData(); - var labelLayoutList = []; - var cx; - var cy; - var hasLabelRotate = false; - var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN; - var viewRect = data.getLayout('viewRect'); - var r = data.getLayout('r'); - var viewWidth = viewRect.width; - var viewLeft = viewRect.x; - var viewTop = viewRect.y; - var viewHeight = viewRect.height; - - function setNotShow(el) { - el.ignore = true; - } - - function isLabelShown(label) { - if (!label.ignore) { - return true; - } - - for (var key in label.states) { - if (label.states[key].ignore === false) { - return true; - } - } - - return false; - } - - data.each(function (idx) { - var sector = data.getItemGraphicEl(idx); - var sectorShape = sector.shape; - var label = sector.getTextContent(); - var labelLine = sector.getTextGuideLine(); - var itemModel = data.getItemModel(idx); - var labelModel = itemModel.getModel('label'); // Use position in normal or emphasis - - var labelPosition = labelModel.get('position') || itemModel.get(['emphasis', 'label', 'position']); - var labelDistance = labelModel.get('distanceToLabelLine'); - var labelAlignTo = labelModel.get('alignTo'); - var edgeDistance = parsePercent(labelModel.get('edgeDistance'), viewWidth); - var bleedMargin = labelModel.get('bleedMargin'); - var labelLineModel = itemModel.getModel('labelLine'); - var labelLineLen = labelLineModel.get('length'); - labelLineLen = parsePercent(labelLineLen, viewWidth); - var labelLineLen2 = labelLineModel.get('length2'); - labelLineLen2 = parsePercent(labelLineLen2, viewWidth); - - if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) { - each$4(label.states, setNotShow); - label.ignore = true; - - if (labelLine) { - each$4(labelLine.states, setNotShow); - labelLine.ignore = true; - } - - return; - } - - if (!isLabelShown(label)) { - return; - } - - var midAngle = (sectorShape.startAngle + sectorShape.endAngle) / 2; - var nx = Math.cos(midAngle); - var ny = Math.sin(midAngle); - var textX; - var textY; - var linePoints; - var textAlign; - cx = sectorShape.cx; - cy = sectorShape.cy; - var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; - - if (labelPosition === 'center') { - textX = sectorShape.cx; - textY = sectorShape.cy; - textAlign = 'center'; - } else { - var x1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * nx : sectorShape.r * nx) + cx; - var y1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * ny : sectorShape.r * ny) + cy; - textX = x1 + nx * 3; - textY = y1 + ny * 3; - - if (!isLabelInside) { - // For roseType - var x2 = x1 + nx * (labelLineLen + r - sectorShape.r); - var y2 = y1 + ny * (labelLineLen + r - sectorShape.r); - var x3 = x2 + (nx < 0 ? -1 : 1) * labelLineLen2; - var y3 = y2; - - if (labelAlignTo === 'edge') { - // Adjust textX because text align of edge is opposite - textX = nx < 0 ? viewLeft + edgeDistance : viewLeft + viewWidth - edgeDistance; - } else { - textX = x3 + (nx < 0 ? -labelDistance : labelDistance); - } - - textY = y3; - linePoints = [[x1, y1], [x2, y2], [x3, y3]]; - } - - textAlign = isLabelInside ? 'center' : labelAlignTo === 'edge' ? nx > 0 ? 'right' : 'left' : nx > 0 ? 'left' : 'right'; - } - - var PI = Math.PI; - var labelRotate = 0; - var rotate = labelModel.get('rotate'); - - if (isNumber(rotate)) { - labelRotate = rotate * (PI / 180); - } else if (labelPosition === 'center') { - labelRotate = 0; - } else if (rotate === 'radial' || rotate === true) { - var radialAngle = nx < 0 ? -midAngle + PI : -midAngle; - labelRotate = radialAngle; - } else if (rotate === 'tangential' && labelPosition !== 'outside' && labelPosition !== 'outer') { - var rad = Math.atan2(nx, ny); - - if (rad < 0) { - rad = PI * 2 + rad; - } - - var isDown = ny > 0; - - if (isDown) { - rad = PI + rad; - } - - labelRotate = rad - PI; - } - - hasLabelRotate = !!labelRotate; - label.x = textX; - label.y = textY; - label.rotation = labelRotate; - label.setStyle({ - verticalAlign: 'middle' - }); // Not sectorShape the inside label - - if (!isLabelInside) { - var textRect = label.getBoundingRect().clone(); - textRect.applyTransform(label.getComputedTransform()); // Text has a default 1px stroke. Exclude this. - - var margin = (label.style.margin || 0) + 2.1; - textRect.y -= margin / 2; - textRect.height += margin; - labelLayoutList.push({ - label: label, - labelLine: labelLine, - position: labelPosition, - len: labelLineLen, - len2: labelLineLen2, - minTurnAngle: labelLineModel.get('minTurnAngle'), - maxSurfaceAngle: labelLineModel.get('maxSurfaceAngle'), - surfaceNormal: new Point(nx, ny), - linePoints: linePoints, - textAlign: textAlign, - labelDistance: labelDistance, - labelAlignTo: labelAlignTo, - edgeDistance: edgeDistance, - bleedMargin: bleedMargin, - rect: textRect, - unconstrainedWidth: textRect.width, - labelStyleWidth: label.style.width - }); - } else { - label.setStyle({ - align: textAlign - }); - var selectState = label.states.select; - - if (selectState) { - selectState.x += label.x; - selectState.y += label.y; - } - } - - sector.setTextConfig({ - inside: isLabelInside - }); - }); - - if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) { - avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop); - } - - for (var i = 0; i < labelLayoutList.length; i++) { - var layout = labelLayoutList[i]; - var label = layout.label; - var labelLine = layout.labelLine; - var notShowLabel = isNaN(label.x) || isNaN(label.y); - - if (label) { - label.setStyle({ - align: layout.textAlign - }); - - if (notShowLabel) { - each$4(label.states, setNotShow); - label.ignore = true; - } - - var selectState = label.states.select; - - if (selectState) { - selectState.x += label.x; - selectState.y += label.y; - } - } - - if (labelLine) { - var linePoints = layout.linePoints; - - if (notShowLabel || !linePoints) { - each$4(labelLine.states, setNotShow); - labelLine.ignore = true; - } else { - limitTurnAngle(linePoints, layout.minTurnAngle); - limitSurfaceAngle(linePoints, layout.surfaceNormal, layout.maxSurfaceAngle); - labelLine.setShape({ - points: linePoints - }); // Set the anchor to the midpoint of sector - - label.__hostTarget.textGuideLineConfig = { - anchor: new Point(linePoints[0][0], linePoints[0][1]) - }; - } - } - } - } - /** - * Piece of pie including Sector, Label, LabelLine - */ - - - var PiePiece = - /** @class */ - function (_super) { - __extends(PiePiece, _super); - - function PiePiece(data, idx, startAngle) { - var _this = _super.call(this) || this; - - _this.z2 = 2; - var text = new ZRText(); - - _this.setTextContent(text); - - _this.updateData(data, idx, startAngle, true); - - return _this; - } - - PiePiece.prototype.updateData = function (data, idx, startAngle, firstCreate) { - var sector = this; - var seriesModel = data.hostModel; - var itemModel = data.getItemModel(idx); - var emphasisModel = itemModel.getModel('emphasis'); - var layout = data.getItemLayout(idx); // cornerRadius & innerCornerRadius doesn't exist in the item layout. Use `0` if null value is specified. - // see `setItemLayout` in `pieLayout.ts`. - - var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout, true), layout); // Ignore NaN data. - - if (isNaN(sectorShape.startAngle)) { - // Use NaN shape to avoid drawing shape. - sector.setShape(sectorShape); - return; - } - - if (firstCreate) { - sector.setShape(sectorShape); - var animationType = seriesModel.getShallow('animationType'); - - if (seriesModel.ecModel.ssr) { - // Use scale animation in SSR mode(opacity?) - // Because CSS SVG animation doesn't support very customized shape animation. - initProps(sector, { - scaleX: 0, - scaleY: 0 - }, seriesModel, { - dataIndex: idx, - isFrom: true - }); - sector.originX = sectorShape.cx; - sector.originY = sectorShape.cy; - } else if (animationType === 'scale') { - sector.shape.r = layout.r0; - initProps(sector, { - shape: { - r: layout.r - } - }, seriesModel, idx); - } // Expansion - else { - if (startAngle != null) { - sector.setShape({ - startAngle: startAngle, - endAngle: startAngle - }); - initProps(sector, { - shape: { - startAngle: layout.startAngle, - endAngle: layout.endAngle - } - }, seriesModel, idx); - } else { - sector.shape.endAngle = layout.startAngle; - updateProps$1(sector, { - shape: { - endAngle: layout.endAngle - } - }, seriesModel, idx); - } - } - } else { - saveOldStyle(sector); // Transition animation from the old shape - - updateProps$1(sector, { - shape: sectorShape - }, seriesModel, idx); - } - - sector.useStyle(data.getItemVisual(idx, 'style')); - setStatesStylesFromModel(sector, itemModel); - var midAngle = (layout.startAngle + layout.endAngle) / 2; - var offset = seriesModel.get('selectedOffset'); - var dx = Math.cos(midAngle) * offset; - var dy = Math.sin(midAngle) * offset; - var cursorStyle = itemModel.getShallow('cursor'); - cursorStyle && sector.attr('cursor', cursorStyle); - - this._updateLabel(seriesModel, data, idx); - - sector.ensureState('emphasis').shape = extend({ - r: layout.r + (emphasisModel.get('scale') ? emphasisModel.get('scaleSize') || 0 : 0) - }, getSectorCornerRadius(emphasisModel.getModel('itemStyle'), layout)); - extend(sector.ensureState('select'), { - x: dx, - y: dy, - shape: getSectorCornerRadius(itemModel.getModel(['select', 'itemStyle']), layout) - }); - extend(sector.ensureState('blur'), { - shape: getSectorCornerRadius(itemModel.getModel(['blur', 'itemStyle']), layout) - }); - var labelLine = sector.getTextGuideLine(); - var labelText = sector.getTextContent(); - labelLine && extend(labelLine.ensureState('select'), { - x: dx, - y: dy - }); // TODO: needs dx, dy in zrender? - - extend(labelText.ensureState('select'), { - x: dx, - y: dy - }); - toggleHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); - }; - - PiePiece.prototype._updateLabel = function (seriesModel, data, idx) { - var sector = this; - var itemModel = data.getItemModel(idx); - var labelLineModel = itemModel.getModel('labelLine'); - var style = data.getItemVisual(idx, 'style'); - var visualColor = style && style.fill; - var visualOpacity = style && style.opacity; - setLabelStyle(sector, getLabelStatesModels(itemModel), { - labelFetcher: data.hostModel, - labelDataIndex: idx, - inheritColor: visualColor, - defaultOpacity: visualOpacity, - defaultText: seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx) - }); - var labelText = sector.getTextContent(); // Set textConfig on sector. - - sector.setTextConfig({ - // reset position, rotation - position: null, - rotation: null - }); // Make sure update style on labelText after setLabelStyle. - // Because setLabelStyle will replace a new style on it. - - labelText.attr({ - z2: 10 - }); - var labelPosition = seriesModel.get(['label', 'position']); - - if (labelPosition !== 'outside' && labelPosition !== 'outer') { - sector.removeTextGuideLine(); - } else { - var polyline = this.getTextGuideLine(); - - if (!polyline) { - polyline = new Polyline(); - this.setTextGuideLine(polyline); - } // Default use item visual color - - - setLabelLineStyle(this, getLabelLineStatesModels(itemModel), { - stroke: visualColor, - opacity: retrieve3(labelLineModel.get(['lineStyle', 'opacity']), visualOpacity, 1) - }); - } - }; - - return PiePiece; - }(Sector); // Pie view - - - var PieView = - /** @class */ - function (_super) { - __extends(PieView, _super); - - function PieView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.ignoreLabelLineUpdate = true; - return _this; - } - - PieView.prototype.render = function (seriesModel, ecModel, api, payload) { - var data = seriesModel.getData(); - var oldData = this._data; - var group = this.group; - var startAngle; // First render - - if (!oldData && data.count() > 0) { - var shape = data.getItemLayout(0); - - for (var s = 1; isNaN(shape && shape.startAngle) && s < data.count(); ++s) { - shape = data.getItemLayout(s); - } - - if (shape) { - startAngle = shape.startAngle; - } - } // remove empty-circle if it exists - - - if (this._emptyCircleSector) { - group.remove(this._emptyCircleSector); - } // when all data are filtered, show lightgray empty circle - - - if (data.count() === 0 && seriesModel.get('showEmptyCircle')) { - var sector = new Sector({ - shape: getBasicPieLayout(seriesModel, api) - }); - sector.useStyle(seriesModel.getModel('emptyCircleStyle').getItemStyle()); - this._emptyCircleSector = sector; - group.add(sector); - } - - data.diff(oldData).add(function (idx) { - var piePiece = new PiePiece(data, idx, startAngle); - data.setItemGraphicEl(idx, piePiece); - group.add(piePiece); - }).update(function (newIdx, oldIdx) { - var piePiece = oldData.getItemGraphicEl(oldIdx); - piePiece.updateData(data, newIdx, startAngle); - piePiece.off('click'); - group.add(piePiece); - data.setItemGraphicEl(newIdx, piePiece); - }).remove(function (idx) { - var piePiece = oldData.getItemGraphicEl(idx); - removeElementWithFadeOut(piePiece, seriesModel, idx); - }).execute(); - pieLabelLayout(seriesModel); // Always use initial animation. - - if (seriesModel.get('animationTypeUpdate') !== 'expansion') { - this._data = data; - } - }; - - PieView.prototype.dispose = function () {}; - - PieView.prototype.containPoint = function (point, seriesModel) { - var data = seriesModel.getData(); - var itemLayout = data.getItemLayout(0); - - if (itemLayout) { - var dx = point[0] - itemLayout.cx; - var dy = point[1] - itemLayout.cy; - var radius = Math.sqrt(dx * dx + dy * dy); - return radius <= itemLayout.r && radius >= itemLayout.r0; - } - }; - - PieView.type = 'pie'; - return PieView; - }(ChartView); - /** - * [Usage]: - * (1) - * createListSimply(seriesModel, ['value']); - * (2) - * createListSimply(seriesModel, { - * coordDimensions: ['value'], - * dimensionsCount: 5 - * }); - */ - - - function createSeriesDataSimply(seriesModel, opt, nameList) { - opt = isArray(opt) && { - coordDimensions: opt - } || extend({ - encodeDefine: seriesModel.getEncode() - }, opt); - var source = seriesModel.getSource(); - var dimensions = prepareSeriesDataSchema(source, opt).dimensions; - var list = new SeriesData(dimensions, seriesModel); - list.initData(source, nameList); - return list; - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * LegendVisualProvider is an bridge that pick encoded color from data and - * provide to the legend component. - */ - - - var LegendVisualProvider = - /** @class */ - function () { - function LegendVisualProvider( // Function to get data after filtered. It stores all the encoding info - getDataWithEncodedVisual, // Function to get raw data before filtered. - getRawData) { - this._getDataWithEncodedVisual = getDataWithEncodedVisual; - this._getRawData = getRawData; - } - - LegendVisualProvider.prototype.getAllNames = function () { - var rawData = this._getRawData(); // We find the name from the raw data. In case it's filtered by the legend component. - // Normally, the name can be found in rawData, but can't be found in filtered data will display as gray. - - - return rawData.mapArray(rawData.getName); - }; - - LegendVisualProvider.prototype.containName = function (name) { - var rawData = this._getRawData(); - - return rawData.indexOfName(name) >= 0; - }; - - LegendVisualProvider.prototype.indexOfName = function (name) { - // Only get data when necessary. - // Because LegendVisualProvider constructor may be new in the stage that data is not prepared yet. - // Invoking Series#getData immediately will throw an error. - var dataWithEncodedVisual = this._getDataWithEncodedVisual(); - - return dataWithEncodedVisual.indexOfName(name); - }; - - LegendVisualProvider.prototype.getItemVisual = function (dataIndex, key) { - // Get encoded visual properties from final filtered data. - var dataWithEncodedVisual = this._getDataWithEncodedVisual(); - - return dataWithEncodedVisual.getItemVisual(dataIndex, key); - }; - - return LegendVisualProvider; - }(); - - var innerData = makeInner(); - - var PieSeriesModel = - /** @class */ - function (_super) { - __extends(PieSeriesModel, _super); - - function PieSeriesModel() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - * @overwrite - */ - - - PieSeriesModel.prototype.init = function (option) { - _super.prototype.init.apply(this, arguments); // Enable legend selection for each data item - // Use a function instead of direct access because data reference may changed - - - this.legendVisualProvider = new LegendVisualProvider(bind$1(this.getData, this), bind$1(this.getRawData, this)); - - this._defaultLabelLine(option); - }; - /** - * @overwrite - */ - - - PieSeriesModel.prototype.mergeOption = function () { - _super.prototype.mergeOption.apply(this, arguments); - }; - /** - * @overwrite - */ - - - PieSeriesModel.prototype.getInitialData = function () { - return createSeriesDataSimply(this, { - coordDimensions: ['value'], - encodeDefaulter: curry$1(makeSeriesEncodeForNameBased, this) - }); - }; - /** - * @overwrite - */ - - - PieSeriesModel.prototype.getDataParams = function (dataIndex) { - var data = this.getData(); // update seats when data is changed - - var dataInner = innerData(data); - var seats = dataInner.seats; - - if (!seats) { - var valueList_1 = []; - data.each(data.mapDimension('value'), function (value) { - valueList_1.push(value); - }); - seats = dataInner.seats = getPercentSeats(valueList_1, data.hostModel.get('percentPrecision')); - } - - var params = _super.prototype.getDataParams.call(this, dataIndex); // seats may be empty when sum is 0 - - - params.percent = seats[dataIndex] || 0; - params.$vars.push('percent'); - return params; - }; - - PieSeriesModel.prototype._defaultLabelLine = function (option) { - // Extend labelLine emphasis - defaultEmphasis(option, 'labelLine', ['show']); - var labelLineNormalOpt = option.labelLine; - var labelLineEmphasisOpt = option.emphasis.labelLine; // Not show label line if `label.normal.show = false` - - labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show; - labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show; - }; - - PieSeriesModel.type = 'series.pie'; - PieSeriesModel.defaultOption = { - // zlevel: 0, - z: 2, - legendHoverLink: true, - colorBy: 'data', - // 默认全局居中 - center: ['50%', '50%'], - radius: [0, '75%'], - // 默认顺时针 - clockwise: true, - startAngle: 90, - endAngle: 'auto', - padAngle: 0, - // 最小角度改为0 - minAngle: 0, - // If the angle of a sector less than `minShowLabelAngle`, - // the label will not be displayed. - minShowLabelAngle: 0, - // 选中时扇区偏移量 - selectedOffset: 10, - // 选择模式,默认关闭,可选single,multiple - // selectedMode: false, - // 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积) - // roseType: null, - percentPrecision: 2, - // If still show when all data zero. - stillShowZeroSum: true, - // cursor: null, - left: 0, - top: 0, - right: 0, - bottom: 0, - width: null, - height: null, - label: { - // color: 'inherit', - // If rotate around circle - rotate: 0, - show: true, - overflow: 'truncate', - // 'outer', 'inside', 'center' - position: 'outer', - // 'none', 'labelLine', 'edge'. Works only when position is 'outer' - alignTo: 'none', - // Closest distance between label and chart edge. - // Works only position is 'outer' and alignTo is 'edge'. - edgeDistance: '25%', - // Works only position is 'outer' and alignTo is not 'edge'. - bleedMargin: 10, - // Distance between text and label line. - distanceToLabelLine: 5 // formatter: 标签文本格式器,同 tooltip.formatter,不支持异步回调 - // 默认使用全局文本样式,详见 textStyle - // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数 - - }, - // Enabled when label.normal.position is 'outer' - labelLine: { - show: true, - // 引导线两段中的第一段长度 - length: 15, - // 引导线两段中的第二段长度 - length2: 15, - smooth: false, - minTurnAngle: 90, - maxSurfaceAngle: 90, - lineStyle: { - // color: 各异, - width: 1, - type: 'solid' - } - }, - itemStyle: { - borderWidth: 1, - borderJoin: 'round' - }, - showEmptyCircle: true, - emptyCircleStyle: { - color: 'lightgray', - opacity: 1 - }, - labelLayout: { - // Hide the overlapped label. - hideOverlap: true - }, - emphasis: { - scale: true, - scaleSize: 5 - }, - // If use strategy to avoid label overlapping - avoidLabelOverlap: true, - // Animation type. Valid values: expansion, scale - animationType: 'expansion', - animationDuration: 1000, - // Animation type when update. Valid values: transition, expansion - animationTypeUpdate: 'transition', - animationEasingUpdate: 'cubicInOut', - animationDurationUpdate: 500, - animationEasing: 'cubicInOut' - }; - return PieSeriesModel; - }(SeriesModel); - - function negativeDataFilter(seriesType) { - return { - seriesType: seriesType, - reset: function (seriesModel, ecModel) { - var data = seriesModel.getData(); - data.filterSelf(function (idx) { - // handle negative value condition - var valueDim = data.mapDimension('value'); - var curValue = data.get(valueDim, idx); - - if (isNumber(curValue) && !isNaN(curValue) && curValue < 0) { - return false; - } - - return true; - }); - } - }; - } - - function install$7(registers) { - registers.registerChartView(PieView); - registers.registerSeriesModel(PieSeriesModel); - createLegacyDataSelectAction('pie', registers.registerAction); - registers.registerLayout(curry$1(pieLayout, 'pie')); - registers.registerProcessor(dataFilter('pie')); - registers.registerProcessor(negativeDataFilter('pie')); - } - - use(install$7); - - var GridModel = - /** @class */ - function (_super) { - __extends(GridModel, _super); - - function GridModel() { - return _super !== null && _super.apply(this, arguments) || this; - } - - GridModel.type = 'grid'; - GridModel.dependencies = ['xAxis', 'yAxis']; - GridModel.layoutMode = 'box'; - GridModel.defaultOption = { - show: false, - // zlevel: 0, - z: 0, - left: '10%', - top: 60, - right: '10%', - bottom: 70, - // If grid size contain label - containLabel: false, - // width: {totalWidth} - left - right, - // height: {totalHeight} - top - bottom, - backgroundColor: 'rgba(0,0,0,0)', - borderWidth: 1, - borderColor: '#ccc' - }; - return GridModel; - }(ComponentModel); - - var CartesianAxisModel = - /** @class */ - function (_super) { - __extends(CartesianAxisModel, _super); - - function CartesianAxisModel() { - return _super !== null && _super.apply(this, arguments) || this; - } - - CartesianAxisModel.prototype.getCoordSysModel = function () { - return this.getReferringComponents('grid', SINGLE_REFERRING).models[0]; - }; - - CartesianAxisModel.type = 'cartesian2dAxis'; - return CartesianAxisModel; - }(ComponentModel); - - mixin(CartesianAxisModel, AxisModelCommonMixin); - var defaultOption = { - show: true, - // zlevel: 0, - z: 0, - // Inverse the axis. - inverse: false, - // Axis name displayed. - name: '', - // 'start' | 'middle' | 'end' - nameLocation: 'end', - // By degree. By default auto rotate by nameLocation. - nameRotate: null, - nameTruncate: { - maxWidth: null, - ellipsis: '...', - placeholder: '.' - }, - // Use global text style by default. - nameTextStyle: {}, - // The gap between axisName and axisLine. - nameGap: 15, - // Default `false` to support tooltip. - silent: false, - // Default `false` to avoid legacy user event listener fail. - triggerEvent: false, - tooltip: { - show: false - }, - axisPointer: {}, - axisLine: { - show: true, - onZero: true, - onZeroAxisIndex: null, - lineStyle: { - color: '#6E7079', - width: 1, - type: 'solid' - }, - // The arrow at both ends the the axis. - symbol: ['none', 'none'], - symbolSize: [10, 15] - }, - axisTick: { - show: true, - // Whether axisTick is inside the grid or outside the grid. - inside: false, - // The length of axisTick. - length: 5, - lineStyle: { - width: 1 - } - }, - axisLabel: { - show: true, - // Whether axisLabel is inside the grid or outside the grid. - inside: false, - rotate: 0, - // true | false | null/undefined (auto) - showMinLabel: null, - // true | false | null/undefined (auto) - showMaxLabel: null, - margin: 8, - // formatter: null, - fontSize: 12 - }, - splitLine: { - show: true, - lineStyle: { - color: ['#E0E6F1'], - width: 1, - type: 'solid' - } - }, - splitArea: { - show: false, - areaStyle: { - color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)'] - } - } - }; - var categoryAxis = merge({ - // The gap at both ends of the axis. For categoryAxis, boolean. - boundaryGap: true, - // Set false to faster category collection. - deduplication: null, - // splitArea: { - // show: false - // }, - splitLine: { - show: false - }, - axisTick: { - // If tick is align with label when boundaryGap is true - alignWithLabel: false, - interval: 'auto' - }, - axisLabel: { - interval: 'auto' - } - }, defaultOption); - var valueAxis = merge({ - boundaryGap: [0, 0], - axisLine: { - // Not shown when other axis is categoryAxis in cartesian - show: 'auto' - }, - axisTick: { - // Not shown when other axis is categoryAxis in cartesian - show: 'auto' - }, - // TODO - // min/max: [30, datamin, 60] or [20, datamin] or [datamin, 60] - splitNumber: 5, - minorTick: { - // Minor tick, not available for cateogry axis. - show: false, - // Split number of minor ticks. The value should be in range of (0, 100) - splitNumber: 5, - // Length of minor tick - length: 3, - // Line style - lineStyle: {// Default to be same with axisTick - } - }, - minorSplitLine: { - show: false, - lineStyle: { - color: '#F4F7FD', - width: 1 - } - } - }, defaultOption); - var timeAxis = merge({ - splitNumber: 6, - axisLabel: { - // To eliminate labels that are not nice - showMinLabel: false, - showMaxLabel: false, - rich: { - primary: { - fontWeight: 'bold' - } - } - }, - splitLine: { - show: false - } - }, valueAxis); - var logAxis = defaults({ - logBase: 10 - }, valueAxis); - var axisDefault = { - category: categoryAxis, - value: valueAxis, - time: timeAxis, - log: logAxis - }; - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - var AXIS_TYPES = { - value: 1, - category: 1, - time: 1, - log: 1 - }; - /** - * Generate sub axis model class - * @param axisName 'x' 'y' 'radius' 'angle' 'parallel' ... - */ - - function axisModelCreator(registers, axisName, BaseAxisModelClass, extraDefaultOption) { - each$4(AXIS_TYPES, function (v, axisType) { - var defaultOption = merge(merge({}, axisDefault[axisType], true), extraDefaultOption, true); - - var AxisModel = - /** @class */ - function (_super) { - __extends(AxisModel, _super); - - function AxisModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = axisName + 'Axis.' + axisType; - return _this; - } - - AxisModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { - var layoutMode = fetchLayoutMode(this); - var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; - var themeModel = ecModel.getTheme(); - merge(option, themeModel.get(axisType + 'Axis')); - merge(option, this.getDefaultOption()); - option.type = getAxisType(option); - - if (layoutMode) { - mergeLayoutParam(option, inputPositionParams, layoutMode); - } - }; - - AxisModel.prototype.optionUpdated = function () { - var thisOption = this.option; - - if (thisOption.type === 'category') { - this.__ordinalMeta = OrdinalMeta.createByAxisModel(this); - } - }; - /** - * Should not be called before all of 'getInitailData' finished. - * Because categories are collected during initializing data. - */ - - - AxisModel.prototype.getCategories = function (rawData) { - var option = this.option; // FIXME - // warning if called before all of 'getInitailData' finished. - - if (option.type === 'category') { - if (rawData) { - return option.data; - } - - return this.__ordinalMeta.categories; - } - }; - - AxisModel.prototype.getOrdinalMeta = function () { - return this.__ordinalMeta; - }; - - AxisModel.type = axisName + 'Axis.' + axisType; - AxisModel.defaultOption = defaultOption; - return AxisModel; - }(BaseAxisModelClass); - - registers.registerComponentModel(AxisModel); - }); - registers.registerSubTypeDefaulter(axisName + 'Axis', getAxisType); - } - - function getAxisType(option) { - // Default axis with data is category axis - return option.type || (option.data ? 'category' : 'value'); - } - - var Cartesian = - /** @class */ - function () { - function Cartesian(name) { - this.type = 'cartesian'; - this._dimList = []; - this._axes = {}; - this.name = name || ''; - } - - Cartesian.prototype.getAxis = function (dim) { - return this._axes[dim]; - }; - - Cartesian.prototype.getAxes = function () { - return map$1(this._dimList, function (dim) { - return this._axes[dim]; - }, this); - }; - - Cartesian.prototype.getAxesByScale = function (scaleType) { - scaleType = scaleType.toLowerCase(); - return filter(this.getAxes(), function (axis) { - return axis.scale.type === scaleType; - }); - }; - - Cartesian.prototype.addAxis = function (axis) { - var dim = axis.dim; - this._axes[dim] = axis; - - this._dimList.push(dim); - }; - - return Cartesian; - }(); - - var cartesian2DDimensions = ['x', 'y']; - - function canCalculateAffineTransform(scale) { - return scale.type === 'interval' || scale.type === 'time'; - } - - var Cartesian2D = - /** @class */ - function (_super) { - __extends(Cartesian2D, _super); - - function Cartesian2D() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'cartesian2d'; - _this.dimensions = cartesian2DDimensions; - return _this; - } - /** - * Calculate an affine transform matrix if two axes are time or value. - * It's mainly for accelartion on the large time series data. - */ - - - Cartesian2D.prototype.calcAffineTransform = function () { - this._transform = this._invTransform = null; - var xAxisScale = this.getAxis('x').scale; - var yAxisScale = this.getAxis('y').scale; - - if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) { - return; - } - - var xScaleExtent = xAxisScale.getExtent(); - var yScaleExtent = yAxisScale.getExtent(); - var start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]); - var end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]); - var xScaleSpan = xScaleExtent[1] - xScaleExtent[0]; - var yScaleSpan = yScaleExtent[1] - yScaleExtent[0]; - - if (!xScaleSpan || !yScaleSpan) { - return; - } // Accelerate data to point calculation on the special large time series data. - - - var scaleX = (end[0] - start[0]) / xScaleSpan; - var scaleY = (end[1] - start[1]) / yScaleSpan; - var translateX = start[0] - xScaleExtent[0] * scaleX; - var translateY = start[1] - yScaleExtent[0] * scaleY; - var m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY]; - this._invTransform = invert([], m); - }; - /** - * Base axis will be used on stacking. - */ - - - Cartesian2D.prototype.getBaseAxis = function () { - return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x'); - }; - - Cartesian2D.prototype.containPoint = function (point) { - var axisX = this.getAxis('x'); - var axisY = this.getAxis('y'); - return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1])); - }; - - Cartesian2D.prototype.containData = function (data) { - return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]); - }; - - Cartesian2D.prototype.containZone = function (data1, data2) { - var zoneDiag1 = this.dataToPoint(data1); - var zoneDiag2 = this.dataToPoint(data2); - var area = this.getArea(); - var zone = new BoundingRect(zoneDiag1[0], zoneDiag1[1], zoneDiag2[0] - zoneDiag1[0], zoneDiag2[1] - zoneDiag1[1]); - return area.intersect(zone); - }; - - Cartesian2D.prototype.dataToPoint = function (data, clamp, out) { - out = out || []; - var xVal = data[0]; - var yVal = data[1]; // Fast path - - if (this._transform // It's supported that if data is like `[Inifity, 123]`, where only Y pixel calculated. - && xVal != null && isFinite(xVal) && yVal != null && isFinite(yVal)) { - return applyTransform$1(out, data, this._transform); - } - - var xAxis = this.getAxis('x'); - var yAxis = this.getAxis('y'); - out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal, clamp)); - out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal, clamp)); - return out; - }; - - Cartesian2D.prototype.clampData = function (data, out) { - var xScale = this.getAxis('x').scale; - var yScale = this.getAxis('y').scale; - var xAxisExtent = xScale.getExtent(); - var yAxisExtent = yScale.getExtent(); - var x = xScale.parse(data[0]); - var y = yScale.parse(data[1]); - out = out || []; - out[0] = Math.min(Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1])); - out[1] = Math.min(Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1])); - return out; - }; - - Cartesian2D.prototype.pointToData = function (point, clamp) { - var out = []; - - if (this._invTransform) { - return applyTransform$1(out, point, this._invTransform); - } - - var xAxis = this.getAxis('x'); - var yAxis = this.getAxis('y'); - out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp); - out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp); - return out; - }; - - Cartesian2D.prototype.getOtherAxis = function (axis) { - return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); - }; - /** - * Get rect area of cartesian. - * Area will have a contain function to determine if a point is in the coordinate system. - */ - - - Cartesian2D.prototype.getArea = function (tolerance) { - tolerance = tolerance || 0; - var xExtent = this.getAxis('x').getGlobalExtent(); - var yExtent = this.getAxis('y').getGlobalExtent(); - var x = Math.min(xExtent[0], xExtent[1]) - tolerance; - var y = Math.min(yExtent[0], yExtent[1]) - tolerance; - var width = Math.max(xExtent[0], xExtent[1]) - x + tolerance; - var height = Math.max(yExtent[0], yExtent[1]) - y + tolerance; - return new BoundingRect(x, y, width, height); - }; - - return Cartesian2D; - }(Cartesian); - - var Axis2D = - /** @class */ - function (_super) { - __extends(Axis2D, _super); - - function Axis2D(dim, scale, coordExtent, axisType, position) { - var _this = _super.call(this, dim, scale, coordExtent) || this; - /** - * Index of axis, can be used as key - * Injected outside. - */ - - - _this.index = 0; - _this.type = axisType || 'value'; - _this.position = position || 'bottom'; - return _this; - } - - Axis2D.prototype.isHorizontal = function () { - var position = this.position; - return position === 'top' || position === 'bottom'; - }; - /** - * Each item cooresponds to this.getExtent(), which - * means globalExtent[0] may greater than globalExtent[1], - * unless `asc` is input. - * - * @param {boolean} [asc] - * @return {Array.} - */ - - - Axis2D.prototype.getGlobalExtent = function (asc) { - var ret = this.getExtent(); - ret[0] = this.toGlobalCoord(ret[0]); - ret[1] = this.toGlobalCoord(ret[1]); - asc && ret[0] > ret[1] && ret.reverse(); - return ret; - }; - - Axis2D.prototype.pointToData = function (point, clamp) { - return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); - }; - /** - * Set ordinalSortInfo - * @param info new OrdinalSortInfo - */ - - - Axis2D.prototype.setCategorySortInfo = function (info) { - if (this.type !== 'category') { - return false; - } - - this.model.option.categorySortInfo = info; - this.scale.setSortInfo(info); - }; - - return Axis2D; - }(Axis); - /** - * Can only be called after coordinate system creation stage. - * (Can be called before coordinate system update stage). - */ - - - function layout(gridModel, axisModel, opt) { - opt = opt || {}; - var grid = gridModel.coordinateSystem; - var axis = axisModel.axis; - var layout = {}; - var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0]; - var rawAxisPosition = axis.position; - var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition; - var axisDim = axis.dim; - var rect = grid.getRect(); - var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; - var idx = { - left: 0, - right: 1, - top: 0, - bottom: 1, - onZero: 2 - }; - var axisOffset = axisModel.get('offset') || 0; - var posBound = axisDim === 'x' ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] : [rectBound[0] - axisOffset, rectBound[1] + axisOffset]; - - if (otherAxisOnZeroOf) { - var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0)); - posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]); - } // Axis position - - - layout.position = [axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]]; // Axis rotation - - layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); // Tick and label direction, x y is axisDim - - var dirMap = { - top: -1, - bottom: 1, - left: -1, - right: 1 - }; - layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition]; - layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0; - - if (axisModel.get(['axisTick', 'inside'])) { - layout.tickDirection = -layout.tickDirection; - } - - if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) { - layout.labelDirection = -layout.labelDirection; - } // Special label rotation - - - var labelRotate = axisModel.get(['axisLabel', 'rotate']); - layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; // Over splitLine and splitArea - - layout.z2 = 1; - return layout; - } - - function isCartesian2DSeries(seriesModel) { - return seriesModel.get('coordinateSystem') === 'cartesian2d'; - } - - function findAxisModels(seriesModel) { - var axisModelMap = { - xAxisModel: null, - yAxisModel: null - }; - each$4(axisModelMap, function (v, key) { - var axisType = key.replace(/Model$/, ''); - var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; - { - if (!axisModel) { - throw new Error(axisType + ' "' + retrieve3(seriesModel.get(axisType + 'Index'), seriesModel.get(axisType + 'Id'), 0) + '" not found'); - } - } - axisModelMap[key] = axisModel; - }); - return axisModelMap; - } - - var mathLog = Math.log; - - function alignScaleTicks(scale, axisModel, alignToScale) { - var intervalScaleProto = IntervalScale.prototype; // NOTE: There is a precondition for log scale here: - // In log scale we store _interval and _extent of exponent value. - // So if we use the method of InternalScale to set/get these data. - // It process the exponent value, which is linear and what we want here. - - var alignToTicks = intervalScaleProto.getTicks.call(alignToScale); - var alignToNicedTicks = intervalScaleProto.getTicks.call(alignToScale, true); - var alignToSplitNumber = alignToTicks.length - 1; - var alignToInterval = intervalScaleProto.getInterval.call(alignToScale); - var scaleExtent = getScaleExtent(scale, axisModel); - var rawExtent = scaleExtent.extent; - var isMinFixed = scaleExtent.fixMin; - var isMaxFixed = scaleExtent.fixMax; - - if (scale.type === 'log') { - var logBase = mathLog(scale.base); - rawExtent = [mathLog(rawExtent[0]) / logBase, mathLog(rawExtent[1]) / logBase]; - } - - scale.setExtent(rawExtent[0], rawExtent[1]); - scale.calcNiceExtent({ - splitNumber: alignToSplitNumber, - fixMin: isMinFixed, - fixMax: isMaxFixed - }); - var extent = intervalScaleProto.getExtent.call(scale); // Need to update the rawExtent. - // Because value in rawExtent may be not parsed. e.g. 'dataMin', 'dataMax' - - if (isMinFixed) { - rawExtent[0] = extent[0]; - } - - if (isMaxFixed) { - rawExtent[1] = extent[1]; - } - - var interval = intervalScaleProto.getInterval.call(scale); - var min = rawExtent[0]; - var max = rawExtent[1]; - - if (isMinFixed && isMaxFixed) { - // User set min, max, divide to get new interval - interval = (max - min) / alignToSplitNumber; - } else if (isMinFixed) { - max = rawExtent[0] + interval * alignToSplitNumber; // User set min, expand extent on the other side - - while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])) { - interval = increaseInterval(interval); - max = rawExtent[0] + interval * alignToSplitNumber; - } - } else if (isMaxFixed) { - // User set max, expand extent on the other side - min = rawExtent[1] - interval * alignToSplitNumber; - - while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])) { - interval = increaseInterval(interval); - min = rawExtent[1] - interval * alignToSplitNumber; - } - } else { - var nicedSplitNumber = scale.getTicks().length - 1; - - if (nicedSplitNumber > alignToSplitNumber) { - interval = increaseInterval(interval); - } - - var range = interval * alignToSplitNumber; - max = Math.ceil(rawExtent[1] / interval) * interval; - min = round$2(max - range); // Not change the result that crossing zero. - - if (min < 0 && rawExtent[0] >= 0) { - min = 0; - max = round$2(range); - } else if (max > 0 && rawExtent[1] <= 0) { - max = 0; - min = -round$2(range); - } - } // Adjust min, max based on the extent of alignTo. When min or max is set in alignTo scale - - - var t0 = (alignToTicks[0].value - alignToNicedTicks[0].value) / alignToInterval; - var t1 = (alignToTicks[alignToSplitNumber].value - alignToNicedTicks[alignToSplitNumber].value) / alignToInterval; // NOTE: Must in setExtent -> setInterval -> setNiceExtent order. - - intervalScaleProto.setExtent.call(scale, min + interval * t0, max + interval * t1); - intervalScaleProto.setInterval.call(scale, interval); - - if (t0 || t1) { - intervalScaleProto.setNiceExtent.call(scale, min + interval, max - interval); - } - - { - var ticks = intervalScaleProto.getTicks.call(scale); - - if (ticks[1] && (!isValueNice(interval) || getPrecisionSafe(ticks[1].value) > getPrecisionSafe(interval))) { - warn( // eslint-disable-next-line - "The ticks may be not readable when set min: " + axisModel.get('min') + ", max: " + axisModel.get('max') + " and alignTicks: true"); - } - } - } - - var Grid = - /** @class */ - function () { - function Grid(gridModel, ecModel, api) { - // FIXME:TS where used (different from registered type 'cartesian2d')? - this.type = 'grid'; - this._coordsMap = {}; - this._coordsList = []; - this._axesMap = {}; - this._axesList = []; - this.axisPointerEnabled = true; - this.dimensions = cartesian2DDimensions; - - this._initCartesian(gridModel, ecModel, api); - - this.model = gridModel; - } - - Grid.prototype.getRect = function () { - return this._rect; - }; - - Grid.prototype.update = function (ecModel, api) { - var axesMap = this._axesMap; - - this._updateScale(ecModel, this.model); - - function updateAxisTicks(axes) { - var alignTo; // Axis is added in order of axisIndex. - - var axesIndices = keys(axes); - var len = axesIndices.length; - - if (!len) { - return; - } - - var axisNeedsAlign = []; // Process once and calculate the ticks for those don't use alignTicks. - - for (var i = len - 1; i >= 0; i--) { - var idx = +axesIndices[i]; // Convert to number. - - var axis = axes[idx]; - var model = axis.model; - var scale = axis.scale; - - if ( // Only value and log axis without interval support alignTicks. - isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) { - axisNeedsAlign.push(axis); - } else { - niceScaleExtent(scale, model); - - if (isIntervalOrLogScale(scale)) { - // Can only align to interval or log axis. - alignTo = axis; - } - } - } // All axes has set alignTicks. Pick the first one. - // PENDING. Should we find the axis that both set interval, min, max and align to this one? - - - if (axisNeedsAlign.length) { - if (!alignTo) { - alignTo = axisNeedsAlign.pop(); - niceScaleExtent(alignTo.scale, alignTo.model); - } - - each$4(axisNeedsAlign, function (axis) { - alignScaleTicks(axis.scale, axis.model, alignTo.scale); - }); - } - } - - updateAxisTicks(axesMap.x); - updateAxisTicks(axesMap.y); // Key: axisDim_axisIndex, value: boolean, whether onZero target. - - var onZeroRecords = {}; - each$4(axesMap.x, function (xAxis) { - fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords); - }); - each$4(axesMap.y, function (yAxis) { - fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords); - }); // Resize again if containLabel is enabled - // FIXME It may cause getting wrong grid size in data processing stage - - this.resize(this.model, api); - }; - /** - * Resize the grid - */ - - - Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) { - var boxLayoutParams = gridModel.getBoxLayoutParams(); - var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel'); - var gridRect = getLayoutRect(boxLayoutParams, { - width: api.getWidth(), - height: api.getHeight() - }); - this._rect = gridRect; - var axesList = this._axesList; - adjustAxes(); // Minus label size - - if (isContainLabel) { - each$4(axesList, function (axis) { - if (!axis.model.get(['axisLabel', 'inside'])) { - var labelUnionRect = estimateLabelUnionRect(axis); - - if (labelUnionRect) { - var dim = axis.isHorizontal() ? 'height' : 'width'; - var margin = axis.model.get(['axisLabel', 'margin']); - gridRect[dim] -= labelUnionRect[dim] + margin; - - if (axis.position === 'top') { - gridRect.y += labelUnionRect.height + margin; - } else if (axis.position === 'left') { - gridRect.x += labelUnionRect.width + margin; - } - } - } - }); - adjustAxes(); - } - - each$4(this._coordsList, function (coord) { - // Calculate affine matrix to accelerate the data to point transform. - // If all the axes scales are time or value. - coord.calcAffineTransform(); - }); - - function adjustAxes() { - each$4(axesList, function (axis) { - var isHorizontal = axis.isHorizontal(); - var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; - var idx = axis.inverse ? 1 : 0; - axis.setExtent(extent[idx], extent[1 - idx]); - updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y); - }); - } - }; - - Grid.prototype.getAxis = function (dim, axisIndex) { - var axesMapOnDim = this._axesMap[dim]; - - if (axesMapOnDim != null) { - return axesMapOnDim[axisIndex || 0]; - } - }; - - Grid.prototype.getAxes = function () { - return this._axesList.slice(); - }; - - Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) { - if (xAxisIndex != null && yAxisIndex != null) { - var key = 'x' + xAxisIndex + 'y' + yAxisIndex; - return this._coordsMap[key]; - } - - if (isObject$2(xAxisIndex)) { - yAxisIndex = xAxisIndex.yAxisIndex; - xAxisIndex = xAxisIndex.xAxisIndex; - } - - for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { - if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) { - return coordList[i]; - } - } - }; - - Grid.prototype.getCartesians = function () { - return this._coordsList.slice(); - }; - /** - * @implements - */ - - - Grid.prototype.convertToPixel = function (ecModel, finder, value) { - var target = this._findConvertTarget(finder); - - return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null; - }; - /** - * @implements - */ - - - Grid.prototype.convertFromPixel = function (ecModel, finder, value) { - var target = this._findConvertTarget(finder); - - return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null; - }; - - Grid.prototype._findConvertTarget = function (finder) { - var seriesModel = finder.seriesModel; - var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; - var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; - var gridModel = finder.gridModel; - var coordsList = this._coordsList; - var cartesian; - var axis; - - if (seriesModel) { - cartesian = seriesModel.coordinateSystem; - indexOf(coordsList, cartesian) < 0 && (cartesian = null); - } else if (xAxisModel && yAxisModel) { - cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); - } else if (xAxisModel) { - axis = this.getAxis('x', xAxisModel.componentIndex); - } else if (yAxisModel) { - axis = this.getAxis('y', yAxisModel.componentIndex); - } // Lowest priority. - else if (gridModel) { - var grid = gridModel.coordinateSystem; - - if (grid === this) { - cartesian = this._coordsList[0]; - } - } - - return { - cartesian: cartesian, - axis: axis - }; - }; - /** - * @implements - */ - - - Grid.prototype.containPoint = function (point) { - var coord = this._coordsList[0]; - - if (coord) { - return coord.containPoint(point); - } - }; - /** - * Initialize cartesian coordinate systems - */ - - - Grid.prototype._initCartesian = function (gridModel, ecModel, api) { - var _this = this; - - var grid = this; - var axisPositionUsed = { - left: false, - right: false, - top: false, - bottom: false - }; - var axesMap = { - x: {}, - y: {} - }; - var axesCount = { - x: 0, - y: 0 - }; // Create axis - - ecModel.eachComponent('xAxis', createAxisCreator('x'), this); - ecModel.eachComponent('yAxis', createAxisCreator('y'), this); - - if (!axesCount.x || !axesCount.y) { - // Roll back when there no either x or y axis - this._axesMap = {}; - this._axesList = []; - return; - } - - this._axesMap = axesMap; // Create cartesian2d - - each$4(axesMap.x, function (xAxis, xAxisIndex) { - each$4(axesMap.y, function (yAxis, yAxisIndex) { - var key = 'x' + xAxisIndex + 'y' + yAxisIndex; - var cartesian = new Cartesian2D(key); - cartesian.master = _this; - cartesian.model = gridModel; - _this._coordsMap[key] = cartesian; - - _this._coordsList.push(cartesian); - - cartesian.addAxis(xAxis); - cartesian.addAxis(yAxis); - }); - }); - - function createAxisCreator(dimName) { - return function (axisModel, idx) { - if (!isAxisUsedInTheGrid(axisModel, gridModel)) { - return; - } - - var axisPosition = axisModel.get('position'); - - if (dimName === 'x') { - // Fix position - if (axisPosition !== 'top' && axisPosition !== 'bottom') { - // Default bottom of X - axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom'; - } - } else { - // Fix position - if (axisPosition !== 'left' && axisPosition !== 'right') { - // Default left of Y - axisPosition = axisPositionUsed.left ? 'right' : 'left'; - } - } - - axisPositionUsed[axisPosition] = true; - var axis = new Axis2D(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition); - var isCategory = axis.type === 'category'; - axis.onBand = isCategory && axisModel.get('boundaryGap'); - axis.inverse = axisModel.get('inverse'); // Inject axis into axisModel - - axisModel.axis = axis; // Inject axisModel into axis - - axis.model = axisModel; // Inject grid info axis - - axis.grid = grid; // Index of axis, can be used as key - - axis.index = idx; - - grid._axesList.push(axis); - - axesMap[dimName][idx] = axis; - axesCount[dimName]++; - }; - } - }; - /** - * Update cartesian properties from series. - */ - - - Grid.prototype._updateScale = function (ecModel, gridModel) { - // Reset scale - each$4(this._axesList, function (axis) { - axis.scale.setExtent(Infinity, -Infinity); - - if (axis.type === 'category') { - var categorySortInfo = axis.model.get('categorySortInfo'); - axis.scale.setSortInfo(categorySortInfo); - } - }); - ecModel.eachSeries(function (seriesModel) { - if (isCartesian2DSeries(seriesModel)) { - var axesModelMap = findAxisModels(seriesModel); - var xAxisModel = axesModelMap.xAxisModel; - var yAxisModel = axesModelMap.yAxisModel; - - if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) { - return; - } - - var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); - var data = seriesModel.getData(); - var xAxis = cartesian.getAxis('x'); - var yAxis = cartesian.getAxis('y'); - unionExtent(data, xAxis); - unionExtent(data, yAxis); - } - }, this); - - function unionExtent(data, axis) { - each$4(getDataDimensionsOnAxis(data, axis.dim), function (dim) { - axis.scale.unionExtentFromData(data, dim); - }); - } - }; - /** - * @param dim 'x' or 'y' or 'auto' or null/undefined - */ - - - Grid.prototype.getTooltipAxes = function (dim) { - var baseAxes = []; - var otherAxes = []; - each$4(this.getCartesians(), function (cartesian) { - var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); - var otherAxis = cartesian.getOtherAxis(baseAxis); - indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); - indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); - }); - return { - baseAxes: baseAxes, - otherAxes: otherAxes - }; - }; - - Grid.create = function (ecModel, api) { - var grids = []; - ecModel.eachComponent('grid', function (gridModel, idx) { - var grid = new Grid(gridModel, ecModel, api); - grid.name = 'grid_' + idx; // dataSampling requires axis extent, so resize - // should be performed in create stage. - - grid.resize(gridModel, api, true); - gridModel.coordinateSystem = grid; - grids.push(grid); - }); // Inject the coordinateSystems into seriesModel - - ecModel.eachSeries(function (seriesModel) { - if (!isCartesian2DSeries(seriesModel)) { - return; - } - - var axesModelMap = findAxisModels(seriesModel); - var xAxisModel = axesModelMap.xAxisModel; - var yAxisModel = axesModelMap.yAxisModel; - var gridModel = xAxisModel.getCoordSysModel(); - { - if (!gridModel) { - throw new Error('Grid "' + retrieve3(xAxisModel.get('gridIndex'), xAxisModel.get('gridId'), 0) + '" not found'); - } - - if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { - throw new Error('xAxis and yAxis must use the same grid'); - } - } - var grid = gridModel.coordinateSystem; - seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); - }); - return grids; - }; // For deciding which dimensions to use when creating list data - - - Grid.dimensions = cartesian2DDimensions; - return Grid; - }(); - /** - * Check if the axis is used in the specified grid. - */ - - - function isAxisUsedInTheGrid(axisModel, gridModel) { - return axisModel.getCoordSysModel() === gridModel; - } - - function fixAxisOnZero(axesMap, otherAxisDim, axis, // Key: see `getOnZeroRecordKey` - onZeroRecords) { - axis.getAxesOnZeroOf = function () { - // TODO: onZero of multiple axes. - return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : []; - }; // onZero can not be enabled in these two situations: - // 1. When any other axis is a category axis. - // 2. When no axis is cross 0 point. - - - var otherAxes = axesMap[otherAxisDim]; - var otherAxisOnZeroOf; - var axisModel = axis.model; - var onZero = axisModel.get(['axisLine', 'onZero']); - var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']); - - if (!onZero) { - return; - } // If target axis is specified. - - - if (onZeroAxisIndex != null) { - if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) { - otherAxisOnZeroOf = otherAxes[onZeroAxisIndex]; - } - } else { - // Find the first available other axis. - for (var idx in otherAxes) { - if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) // Consider that two Y axes on one value axis, - // if both onZero, the two Y axes overlap. - && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) { - otherAxisOnZeroOf = otherAxes[idx]; - break; - } - } - } - - if (otherAxisOnZeroOf) { - onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true; - } - - function getOnZeroRecordKey(axis) { - return axis.dim + '_' + axis.index; - } - } - - function canOnZeroToAxis(axis) { - return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis); - } - - function updateAxisTransform(axis, coordBase) { - var axisExtent = axis.getExtent(); - var axisExtentSum = axisExtent[0] + axisExtent[1]; // Fast transform - - axis.toGlobalCoord = axis.dim === 'x' ? function (coord) { - return coord + coordBase; - } : function (coord) { - return axisExtentSum - coord + coordBase; - }; - axis.toLocalCoord = axis.dim === 'x' ? function (coord) { - return coord - coordBase; - } : function (coord) { - return axisExtentSum - coord + coordBase; - }; - } - - var PI$1 = Math.PI; - /** - * A final axis is translated and rotated from a "standard axis". - * So opt.position and opt.rotation is required. - * - * A standard axis is and axis from [0, 0] to [0, axisExtent[1]], - * for example: (0, 0) ------------> (0, 50) - * - * nameDirection or tickDirection or labelDirection is 1 means tick - * or label is below the standard axis, whereas is -1 means above - * the standard axis. labelOffset means offset between label and axis, - * which is useful when 'onZero', where axisLabel is in the grid and - * label in outside grid. - * - * Tips: like always, - * positive rotation represents anticlockwise, and negative rotation - * represents clockwise. - * The direction of position coordinate is the same as the direction - * of screen coordinate. - * - * Do not need to consider axis 'inverse', which is auto processed by - * axis extent. - */ - - var AxisBuilder = - /** @class */ - function () { - function AxisBuilder(axisModel, opt) { - this.group = new Group$2(); - this.opt = opt; - this.axisModel = axisModel; // Default value - - defaults(opt, { - labelOffset: 0, - nameDirection: 1, - tickDirection: 1, - labelDirection: 1, - silent: true, - handleAutoShown: function () { - return true; - } - }); // FIXME Not use a separate text group? - - var transformGroup = new Group$2({ - x: opt.position[0], - y: opt.position[1], - rotation: opt.rotation - }); // this.group.add(transformGroup); - // this._transformGroup = transformGroup; - - transformGroup.updateTransform(); - this._transformGroup = transformGroup; - } - - AxisBuilder.prototype.hasBuilder = function (name) { - return !!builders[name]; - }; - - AxisBuilder.prototype.add = function (name) { - builders[name](this.opt, this.axisModel, this.group, this._transformGroup); - }; - - AxisBuilder.prototype.getGroup = function () { - return this.group; - }; - - AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { - var rotationDiff = remRadian(textRotation - axisRotation); - var textAlign; - var textVerticalAlign; - - if (isRadianAroundZero(rotationDiff)) { - // Label is parallel with axis line. - textVerticalAlign = direction > 0 ? 'top' : 'bottom'; - textAlign = 'center'; - } else if (isRadianAroundZero(rotationDiff - PI$1)) { - // Label is inverse parallel with axis line. - textVerticalAlign = direction > 0 ? 'bottom' : 'top'; - textAlign = 'center'; - } else { - textVerticalAlign = 'middle'; - - if (rotationDiff > 0 && rotationDiff < PI$1) { - textAlign = direction > 0 ? 'right' : 'left'; - } else { - textAlign = direction > 0 ? 'left' : 'right'; - } - } - - return { - rotation: rotationDiff, - textAlign: textAlign, - textVerticalAlign: textVerticalAlign - }; - }; - - AxisBuilder.makeAxisEventDataBase = function (axisModel) { - var eventData = { - componentType: axisModel.mainType, - componentIndex: axisModel.componentIndex - }; - eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; - return eventData; - }; - - AxisBuilder.isLabelSilent = function (axisModel) { - var tooltipOpt = axisModel.get('tooltip'); - return axisModel.get('silent') // Consider mouse cursor, add these restrictions. - || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show); - }; - - return AxisBuilder; - }(); - - var builders = { - axisLine: function (opt, axisModel, group, transformGroup) { - var shown = axisModel.get(['axisLine', 'show']); - - if (shown === 'auto' && opt.handleAutoShown) { - shown = opt.handleAutoShown('axisLine'); - } - - if (!shown) { - return; - } - - var extent = axisModel.axis.getExtent(); - var matrix = transformGroup.transform; - var pt1 = [extent[0], 0]; - var pt2 = [extent[1], 0]; - var inverse = pt1[0] > pt2[0]; - - if (matrix) { - applyTransform$1(pt1, pt1, matrix); - applyTransform$1(pt2, pt2, matrix); - } - - var lineStyle = extend({ - lineCap: 'round' - }, axisModel.getModel(['axisLine', 'lineStyle']).getLineStyle()); - var line = new Line({ - shape: { - x1: pt1[0], - y1: pt1[1], - x2: pt2[0], - y2: pt2[1] - }, - style: lineStyle, - strokeContainThreshold: opt.strokeContainThreshold || 5, - silent: true, - z2: 1 - }); - subPixelOptimizeLine(line.shape, line.style.lineWidth); - line.anid = 'line'; - group.add(line); - var arrows = axisModel.get(['axisLine', 'symbol']); - - if (arrows != null) { - var arrowSize = axisModel.get(['axisLine', 'symbolSize']); - - if (isString(arrows)) { - // Use the same arrow for start and end point - arrows = [arrows, arrows]; - } - - if (isString(arrowSize) || isNumber(arrowSize)) { - // Use the same size for width and height - arrowSize = [arrowSize, arrowSize]; - } - - var arrowOffset = normalizeSymbolOffset(axisModel.get(['axisLine', 'symbolOffset']) || 0, arrowSize); - var symbolWidth_1 = arrowSize[0]; - var symbolHeight_1 = arrowSize[1]; - each$4([{ - rotate: opt.rotation + Math.PI / 2, - offset: arrowOffset[0], - r: 0 - }, { - rotate: opt.rotation - Math.PI / 2, - offset: arrowOffset[1], - r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1])) - }], function (point, index) { - if (arrows[index] !== 'none' && arrows[index] != null) { - var symbol = createSymbol(arrows[index], -symbolWidth_1 / 2, -symbolHeight_1 / 2, symbolWidth_1, symbolHeight_1, lineStyle.stroke, true); // Calculate arrow position with offset - - var r = point.r + point.offset; - var pt = inverse ? pt2 : pt1; - symbol.attr({ - rotation: point.rotate, - x: pt[0] + r * Math.cos(opt.rotation), - y: pt[1] - r * Math.sin(opt.rotation), - silent: true, - z2: 11 - }); - group.add(symbol); - } - }); - } - }, - axisTickLabel: function (opt, axisModel, group, transformGroup) { - var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt); - var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt); - fixMinMaxLabelShow(axisModel, labelEls, ticksEls); - buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); // This bit fixes the label overlap issue for the time chart. - // See https://github.com/apache/echarts/issues/14266 for more. - - if (axisModel.get(['axisLabel', 'hideOverlap'])) { - var labelList = prepareLayoutList(map$1(labelEls, function (label) { - return { - label: label, - priority: label.z2, - defaultAttr: { - ignore: label.ignore - } - }; - })); - hideOverlap(labelList); - } - }, - axisName: function (opt, axisModel, group, transformGroup) { - var name = retrieve(opt.axisName, axisModel.get('name')); - - if (!name) { - return; - } - - var nameLocation = axisModel.get('nameLocation'); - var nameDirection = opt.nameDirection; - var textStyleModel = axisModel.getModel('nameTextStyle'); - var gap = axisModel.get('nameGap') || 0; - var extent = axisModel.axis.getExtent(); - var gapSignal = extent[0] > extent[1] ? -1 : 1; - var pos = [nameLocation === 'start' ? extent[0] - gapSignal * gap : nameLocation === 'end' ? extent[1] + gapSignal * gap : (extent[0] + extent[1]) / 2, // Reuse labelOffset. - isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0]; - var labelLayout; - var nameRotation = axisModel.get('nameRotate'); - - if (nameRotation != null) { - nameRotation = nameRotation * PI$1 / 180; // To radian. - } - - var axisNameAvailableWidth; - - if (isNameLocationCenter(nameLocation)) { - labelLayout = AxisBuilder.innerTextLayout(opt.rotation, nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis. - nameDirection); - } else { - labelLayout = endTextLayout(opt.rotation, nameLocation, nameRotation || 0, extent); - axisNameAvailableWidth = opt.axisNameAvailableWidth; - - if (axisNameAvailableWidth != null) { - axisNameAvailableWidth = Math.abs(axisNameAvailableWidth / Math.sin(labelLayout.rotation)); - !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null); - } - } - - var textFont = textStyleModel.getFont(); - var truncateOpt = axisModel.get('nameTruncate', true) || {}; - var ellipsis = truncateOpt.ellipsis; - var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth); - var textEl = new ZRText({ - x: pos[0], - y: pos[1], - rotation: labelLayout.rotation, - silent: AxisBuilder.isLabelSilent(axisModel), - style: createTextStyle$1(textStyleModel, { - text: name, - font: textFont, - overflow: 'truncate', - width: maxWidth, - ellipsis: ellipsis, - fill: textStyleModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']), - align: textStyleModel.get('align') || labelLayout.textAlign, - verticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign - }), - z2: 1 - }); - setTooltipConfig({ - el: textEl, - componentModel: axisModel, - itemName: name - }); - textEl.__fullText = name; // Id for animation - - textEl.anid = 'name'; - - if (axisModel.get('triggerEvent')) { - var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); - eventData.targetType = 'axisName'; - eventData.name = name; - getECData(textEl).eventData = eventData; - } // FIXME - - - transformGroup.add(textEl); - textEl.updateTransform(); - group.add(textEl); - textEl.decomposeTransform(); - } - }; - - function endTextLayout(rotation, textPosition, textRotate, extent) { - var rotationDiff = remRadian(textRotate - rotation); - var textAlign; - var textVerticalAlign; - var inverse = extent[0] > extent[1]; - var onLeft = textPosition === 'start' && !inverse || textPosition !== 'start' && inverse; - - if (isRadianAroundZero(rotationDiff - PI$1 / 2)) { - textVerticalAlign = onLeft ? 'bottom' : 'top'; - textAlign = 'center'; - } else if (isRadianAroundZero(rotationDiff - PI$1 * 1.5)) { - textVerticalAlign = onLeft ? 'top' : 'bottom'; - textAlign = 'center'; - } else { - textVerticalAlign = 'middle'; - - if (rotationDiff < PI$1 * 1.5 && rotationDiff > PI$1 / 2) { - textAlign = onLeft ? 'left' : 'right'; - } else { - textAlign = onLeft ? 'right' : 'left'; - } - } - - return { - rotation: rotationDiff, - textAlign: textAlign, - textVerticalAlign: textVerticalAlign - }; - } - - function fixMinMaxLabelShow(axisModel, labelEls, tickEls) { - if (shouldShowAllLabels(axisModel.axis)) { - return; - } // If min or max are user set, we need to check - // If the tick on min(max) are overlap on their neighbour tick - // If they are overlapped, we need to hide the min(max) tick label - - - var showMinLabel = axisModel.get(['axisLabel', 'showMinLabel']); - var showMaxLabel = axisModel.get(['axisLabel', 'showMaxLabel']); // FIXME - // Have not consider onBand yet, where tick els is more than label els. - - labelEls = labelEls || []; - tickEls = tickEls || []; - var firstLabel = labelEls[0]; - var nextLabel = labelEls[1]; - var lastLabel = labelEls[labelEls.length - 1]; - var prevLabel = labelEls[labelEls.length - 2]; - var firstTick = tickEls[0]; - var nextTick = tickEls[1]; - var lastTick = tickEls[tickEls.length - 1]; - var prevTick = tickEls[tickEls.length - 2]; - - if (showMinLabel === false) { - ignoreEl(firstLabel); - ignoreEl(firstTick); - } else if (isTwoLabelOverlapped(firstLabel, nextLabel)) { - if (showMinLabel) { - ignoreEl(nextLabel); - ignoreEl(nextTick); - } else { - ignoreEl(firstLabel); - ignoreEl(firstTick); - } - } - - if (showMaxLabel === false) { - ignoreEl(lastLabel); - ignoreEl(lastTick); - } else if (isTwoLabelOverlapped(prevLabel, lastLabel)) { - if (showMaxLabel) { - ignoreEl(prevLabel); - ignoreEl(prevTick); - } else { - ignoreEl(lastLabel); - ignoreEl(lastTick); - } - } - } - - function ignoreEl(el) { - el && (el.ignore = true); - } - - function isTwoLabelOverlapped(current, next) { - // current and next has the same rotation. - var firstRect = current && current.getBoundingRect().clone(); - var nextRect = next && next.getBoundingRect().clone(); - - if (!firstRect || !nextRect) { - return; - } // When checking intersect of two rotated labels, we use mRotationBack - // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`. - - - var mRotationBack = identity([]); - rotate(mRotationBack, mRotationBack, -current.rotation); - firstRect.applyTransform(mul([], mRotationBack, current.getLocalTransform())); - nextRect.applyTransform(mul([], mRotationBack, next.getLocalTransform())); - return firstRect.intersect(nextRect); - } - - function isNameLocationCenter(nameLocation) { - return nameLocation === 'middle' || nameLocation === 'center'; - } - - function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, anidPrefix) { - var tickEls = []; - var pt1 = []; - var pt2 = []; - - for (var i = 0; i < ticksCoords.length; i++) { - var tickCoord = ticksCoords[i].coord; - pt1[0] = tickCoord; - pt1[1] = 0; - pt2[0] = tickCoord; - pt2[1] = tickEndCoord; - - if (tickTransform) { - applyTransform$1(pt1, pt1, tickTransform); - applyTransform$1(pt2, pt2, tickTransform); - } // Tick line, Not use group transform to have better line draw - - - var tickEl = new Line({ - shape: { - x1: pt1[0], - y1: pt1[1], - x2: pt2[0], - y2: pt2[1] - }, - style: tickLineStyle, - z2: 2, - autoBatch: true, - silent: true - }); - subPixelOptimizeLine(tickEl.shape, tickEl.style.lineWidth); - tickEl.anid = anidPrefix + '_' + ticksCoords[i].tickValue; - tickEls.push(tickEl); - } - - return tickEls; - } - - function buildAxisMajorTicks(group, transformGroup, axisModel, opt) { - var axis = axisModel.axis; - var tickModel = axisModel.getModel('axisTick'); - var shown = tickModel.get('show'); - - if (shown === 'auto' && opt.handleAutoShown) { - shown = opt.handleAutoShown('axisTick'); - } - - if (!shown || axis.scale.isBlank()) { - return; - } - - var lineStyleModel = tickModel.getModel('lineStyle'); - var tickEndCoord = opt.tickDirection * tickModel.get('length'); - var ticksCoords = axis.getTicksCoords(); - var ticksEls = createTicks(ticksCoords, transformGroup.transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), { - stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) - }), 'ticks'); - - for (var i = 0; i < ticksEls.length; i++) { - group.add(ticksEls[i]); - } - - return ticksEls; - } - - function buildAxisMinorTicks(group, transformGroup, axisModel, tickDirection) { - var axis = axisModel.axis; - var minorTickModel = axisModel.getModel('minorTick'); - - if (!minorTickModel.get('show') || axis.scale.isBlank()) { - return; - } - - var minorTicksCoords = axis.getMinorTicksCoords(); - - if (!minorTicksCoords.length) { - return; - } - - var lineStyleModel = minorTickModel.getModel('lineStyle'); - var tickEndCoord = tickDirection * minorTickModel.get('length'); - var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), { - stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) - })); - - for (var i = 0; i < minorTicksCoords.length; i++) { - var minorTicksEls = createTicks(minorTicksCoords[i], transformGroup.transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i); - - for (var k = 0; k < minorTicksEls.length; k++) { - group.add(minorTicksEls[k]); - } - } - } - - function buildAxisLabel(group, transformGroup, axisModel, opt) { - var axis = axisModel.axis; - var show = retrieve(opt.axisLabelShow, axisModel.get(['axisLabel', 'show'])); - - if (!show || axis.scale.isBlank()) { - return; - } - - var labelModel = axisModel.getModel('axisLabel'); - var labelMargin = labelModel.get('margin'); - var labels = axis.getViewLabels(); // Special label rotate. - - var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI$1 / 180; - var labelLayout = AxisBuilder.innerTextLayout(opt.rotation, labelRotation, opt.labelDirection); - var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true); - var labelEls = []; - var silent = AxisBuilder.isLabelSilent(axisModel); - var triggerEvent = axisModel.get('triggerEvent'); - each$4(labels, function (labelItem, index) { - var tickValue = axis.scale.type === 'ordinal' ? axis.scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue; - var formattedLabel = labelItem.formattedLabel; - var rawLabel = labelItem.rawLabel; - var itemLabelModel = labelModel; - - if (rawCategoryData && rawCategoryData[tickValue]) { - var rawCategoryItem = rawCategoryData[tickValue]; - - if (isObject$2(rawCategoryItem) && rawCategoryItem.textStyle) { - itemLabelModel = new Model(rawCategoryItem.textStyle, labelModel, axisModel.ecModel); - } - } - - var textColor = itemLabelModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']); - var tickCoord = axis.dataToCoord(tickValue); - var align = itemLabelModel.getShallow('align', true) || labelLayout.textAlign; - var alignMin = retrieve2(itemLabelModel.getShallow('alignMinLabel', true), align); - var alignMax = retrieve2(itemLabelModel.getShallow('alignMaxLabel', true), align); - var verticalAlign = itemLabelModel.getShallow('verticalAlign', true) || itemLabelModel.getShallow('baseline', true) || labelLayout.textVerticalAlign; - var verticalAlignMin = retrieve2(itemLabelModel.getShallow('verticalAlignMinLabel', true), verticalAlign); - var verticalAlignMax = retrieve2(itemLabelModel.getShallow('verticalAlignMaxLabel', true), verticalAlign); - var textEl = new ZRText({ - x: tickCoord, - y: opt.labelOffset + opt.labelDirection * labelMargin, - rotation: labelLayout.rotation, - silent: silent, - z2: 10 + (labelItem.level || 0), - style: createTextStyle$1(itemLabelModel, { - text: formattedLabel, - align: index === 0 ? alignMin : index === labels.length - 1 ? alignMax : align, - verticalAlign: index === 0 ? verticalAlignMin : index === labels.length - 1 ? verticalAlignMax : verticalAlign, - fill: isFunction(textColor) ? textColor( // (1) In category axis with data zoom, tick is not the original - // index of axis.data. So tick should not be exposed to user - // in category axis. - // (2) Compatible with previous version, which always use formatted label as - // input. But in interval scale the formatted label is like '223,445', which - // maked user replace ','. So we modify it to return original val but remain - // it as 'string' to avoid error in replacing. - axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, index) : textColor - }) - }); - textEl.anid = 'label_' + tickValue; // Pack data for mouse event - - if (triggerEvent) { - var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); - eventData.targetType = 'axisLabel'; - eventData.value = rawLabel; - eventData.tickIndex = index; - - if (axis.type === 'category') { - eventData.dataIndex = tickValue; - } - - getECData(textEl).eventData = eventData; - } // FIXME - - - transformGroup.add(textEl); - textEl.updateTransform(); - labelEls.push(textEl); - group.add(textEl); - textEl.decomposeTransform(); - }); - return labelEls; - } // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. - // allAxesInfo should be updated when setOption performed. - - - function collect(ecModel, api) { - var result = { - /** - * key: makeKey(axis.model) - * value: { - * axis, - * coordSys, - * axisPointerModel, - * triggerTooltip, - * triggerEmphasis, - * involveSeries, - * snap, - * seriesModels, - * seriesDataCount - * } - */ - axesInfo: {}, - seriesInvolved: false, - - /** - * key: makeKey(coordSys.model) - * value: Object: key makeKey(axis.model), value: axisInfo - */ - coordSysAxesInfo: {}, - coordSysMap: {} - }; - collectAxesInfo(result, ecModel, api); // Check seriesInvolved for performance, in case too many series in some chart. - - result.seriesInvolved && collectSeriesInfo(result, ecModel); - return result; - } - - function collectAxesInfo(result, ecModel, api) { - var globalTooltipModel = ecModel.getComponent('tooltip'); - var globalAxisPointerModel = ecModel.getComponent('axisPointer'); // links can only be set on global. - - var linksOption = globalAxisPointerModel.get('link', true) || []; - var linkGroups = []; // Collect axes info. - - each$4(api.getCoordinateSystems(), function (coordSys) { - // Some coordinate system do not support axes, like geo. - if (!coordSys.axisPointerEnabled) { - return; - } - - var coordSysKey = makeKey(coordSys.model); - var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {}; - result.coordSysMap[coordSysKey] = coordSys; // Set tooltip (like 'cross') is a convenient way to show axisPointer - // for user. So we enable setting tooltip on coordSys model. - - var coordSysModel = coordSys.model; - var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel); - each$4(coordSys.getAxes(), curry$1(saveTooltipAxisInfo, false, null)); // If axis tooltip used, choose tooltip axis for each coordSys. - // Notice this case: coordSys is `grid` but not `cartesian2D` here. - - if (coordSys.getTooltipAxes && globalTooltipModel // If tooltip.showContent is set as false, tooltip will not - // show but axisPointer will show as normal. - && baseTooltipModel.get('show')) { - // Compatible with previous logic. But series.tooltip.trigger: 'axis' - // or series.data[n].tooltip.trigger: 'axis' are not support any more. - var triggerAxis = baseTooltipModel.get('trigger') === 'axis'; - var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross'; - var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis'])); - - if (triggerAxis || cross) { - each$4(tooltipAxes.baseAxes, curry$1(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis)); - } - - if (cross) { - each$4(tooltipAxes.otherAxes, curry$1(saveTooltipAxisInfo, 'cross', false)); - } - } // fromTooltip: true | false | 'cross' - // triggerTooltip: true | false | null - - - function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) { - var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel); - var axisPointerShow = axisPointerModel.get('show'); - - if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) { - return; - } - - if (triggerTooltip == null) { - triggerTooltip = axisPointerModel.get('triggerTooltip'); - } - - axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel; - var snap = axisPointerModel.get('snap'); - var triggerEmphasis = axisPointerModel.get('triggerEmphasis'); - var axisKey = makeKey(axis.model); - var involveSeries = triggerTooltip || snap || axis.type === 'category'; // If result.axesInfo[key] exist, override it (tooltip has higher priority). - - var axisInfo = result.axesInfo[axisKey] = { - key: axisKey, - axis: axis, - coordSys: coordSys, - axisPointerModel: axisPointerModel, - triggerTooltip: triggerTooltip, - triggerEmphasis: triggerEmphasis, - involveSeries: involveSeries, - snap: snap, - useHandle: isHandleTrigger(axisPointerModel), - seriesModels: [], - linkGroup: null - }; - axesInfoInCoordSys[axisKey] = axisInfo; - result.seriesInvolved = result.seriesInvolved || involveSeries; - var groupIndex = getLinkGroupIndex(linksOption, axis); - - if (groupIndex != null) { - var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = { - axesInfo: {} - }); - linkGroup.axesInfo[axisKey] = axisInfo; - linkGroup.mapper = linksOption[groupIndex].mapper; - axisInfo.linkGroup = linkGroup; - } - } - }); - } - - function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) { - var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer'); - var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z']; - var volatileOption = {}; - each$4(fields, function (field) { - volatileOption[field] = clone$3(tooltipAxisPointerModel.get(field)); - }); // category axis do not auto snap, otherwise some tick that do not - // has value can not be hovered. value/time/log axis default snap if - // triggered from tooltip and trigger tooltip. - - volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; // Compatible with previous behavior, tooltip axis does not show label by default. - // Only these properties can be overridden from tooltip to axisPointer. - - if (tooltipAxisPointerModel.get('type') === 'cross') { - volatileOption.type = 'line'; - } - - var labelOption = volatileOption.label || (volatileOption.label = {}); // Follow the convention, do not show label when triggered by tooltip by default. - - labelOption.show == null && (labelOption.show = false); - - if (fromTooltip === 'cross') { - // When 'cross', both axes show labels. - var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']); - labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; // If triggerTooltip, this is a base axis, which should better not use cross style - // (cross style is dashed by default) - - if (!triggerTooltip) { - var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle'); - crossStyle && defaults(labelOption, crossStyle.textStyle); - } - } - - return axis.model.getModel('axisPointer', new Model(volatileOption, globalAxisPointerModel, ecModel)); - } - - function collectSeriesInfo(result, ecModel) { - // Prepare data for axis trigger - ecModel.eachSeries(function (seriesModel) { - // Notice this case: this coordSys is `cartesian2D` but not `grid`. - var coordSys = seriesModel.coordinateSystem; - var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true); - var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true); - - if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) { - return; - } - - each$4(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) { - var axis = axisInfo.axis; - - if (coordSys.getAxis(axis.dim) === axis) { - axisInfo.seriesModels.push(seriesModel); - axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0); - axisInfo.seriesDataCount += seriesModel.getData().count(); - } - }); - }); - } - /** - * For example: - * { - * axisPointer: { - * links: [{ - * xAxisIndex: [2, 4], - * yAxisIndex: 'all' - * }, { - * xAxisId: ['a5', 'a7'], - * xAxisName: 'xxx' - * }] - * } - * } - */ - - - function getLinkGroupIndex(linksOption, axis) { - var axisModel = axis.model; - var dim = axis.dim; - - for (var i = 0; i < linksOption.length; i++) { - var linkOption = linksOption[i] || {}; - - if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) { - return i; - } - } - } - - function checkPropInLink(linkPropValue, axisPropValue) { - return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue; - } - - function fixValue(axisModel) { - var axisInfo = getAxisInfo(axisModel); - - if (!axisInfo) { - return; - } - - var axisPointerModel = axisInfo.axisPointerModel; - var scale = axisInfo.axis.scale; - var option = axisPointerModel.option; - var status = axisPointerModel.get('status'); - var value = axisPointerModel.get('value'); // Parse init value for category and time axis. - - if (value != null) { - value = scale.parse(value); - } - - var useHandle = isHandleTrigger(axisPointerModel); // If `handle` used, `axisPointer` will always be displayed, so value - // and status should be initialized. - - if (status == null) { - option.status = useHandle ? 'show' : 'hide'; - } - - var extent = scale.getExtent().slice(); - extent[0] > extent[1] && extent.reverse(); - - if ( // Pick a value on axis when initializing. - value == null // If both `handle` and `dataZoom` are used, value may be out of axis extent, - // where we should re-pick a value to keep `handle` displaying normally. - || value > extent[1]) { - // Make handle displayed on the end of the axis when init, which looks better. - value = extent[1]; - } - - if (value < extent[0]) { - value = extent[0]; - } - - option.value = value; - - if (useHandle) { - option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show'; - } - } - - function getAxisInfo(axisModel) { - var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo; - return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)]; - } - - function getAxisPointerModel(axisModel) { - var axisInfo = getAxisInfo(axisModel); - return axisInfo && axisInfo.axisPointerModel; - } - - function isHandleTrigger(axisPointerModel) { - return !!axisPointerModel.get(['handle', 'show']); - } - /** - * @param {module:echarts/model/Model} model - * @return {string} unique key - */ - - - function makeKey(model) { - return model.type + '||' + model.id; - } - - var axisPointerClazz = {}; - /** - * Base class of AxisView. - */ - - var AxisView = - /** @class */ - function (_super) { - __extends(AxisView, _super); - - function AxisView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = AxisView.type; - return _this; - } - /** - * @override - */ - - - AxisView.prototype.render = function (axisModel, ecModel, api, payload) { - // FIXME - // This process should proformed after coordinate systems updated - // (axis scale updated), and should be performed each time update. - // So put it here temporarily, although it is not appropriate to - // put a model-writing procedure in `view`. - this.axisPointerClass && fixValue(axisModel); - - _super.prototype.render.apply(this, arguments); - - this._doUpdateAxisPointerClass(axisModel, api, true); - }; - /** - * Action handler. - */ - - - AxisView.prototype.updateAxisPointer = function (axisModel, ecModel, api, payload) { - this._doUpdateAxisPointerClass(axisModel, api, false); - }; - /** - * @override - */ - - - AxisView.prototype.remove = function (ecModel, api) { - var axisPointer = this._axisPointer; - axisPointer && axisPointer.remove(api); - }; - /** - * @override - */ - - - AxisView.prototype.dispose = function (ecModel, api) { - this._disposeAxisPointer(api); - - _super.prototype.dispose.apply(this, arguments); - }; - - AxisView.prototype._doUpdateAxisPointerClass = function (axisModel, api, forceRender) { - var Clazz = AxisView.getAxisPointerClass(this.axisPointerClass); - - if (!Clazz) { - return; - } - - var axisPointerModel = getAxisPointerModel(axisModel); - axisPointerModel ? (this._axisPointer || (this._axisPointer = new Clazz())).render(axisModel, axisPointerModel, api, forceRender) : this._disposeAxisPointer(api); - }; - - AxisView.prototype._disposeAxisPointer = function (api) { - this._axisPointer && this._axisPointer.dispose(api); - this._axisPointer = null; - }; - - AxisView.registerAxisPointerClass = function (type, clazz) { - { - if (axisPointerClazz[type]) { - throw new Error('axisPointer ' + type + ' exists'); - } - } - axisPointerClazz[type] = clazz; - }; - - AxisView.getAxisPointerClass = function (type) { - return type && axisPointerClazz[type]; - }; - - AxisView.type = 'axis'; - return AxisView; - }(ComponentView); - - var inner$3 = makeInner(); - - function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) { - var axis = axisModel.axis; - - if (axis.scale.isBlank()) { - return; - } // TODO: TYPE - - - var splitAreaModel = axisModel.getModel('splitArea'); - var areaStyleModel = splitAreaModel.getModel('areaStyle'); - var areaColors = areaStyleModel.get('color'); - var gridRect = gridModel.coordinateSystem.getRect(); - var ticksCoords = axis.getTicksCoords({ - tickModel: splitAreaModel, - clamp: true - }); - - if (!ticksCoords.length) { - return; - } // For Making appropriate splitArea animation, the color and anid - // should be corresponding to previous one if possible. - - - var areaColorsLen = areaColors.length; - var lastSplitAreaColors = inner$3(axisView).splitAreaColors; - var newSplitAreaColors = createHashMap(); - var colorIndex = 0; - - if (lastSplitAreaColors) { - for (var i = 0; i < ticksCoords.length; i++) { - var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue); - - if (cIndex != null) { - colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen; - break; - } - } - } - - var prev = axis.toGlobalCoord(ticksCoords[0].coord); - var areaStyle = areaStyleModel.getAreaStyle(); - areaColors = isArray(areaColors) ? areaColors : [areaColors]; - - for (var i = 1; i < ticksCoords.length; i++) { - var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); - var x = void 0; - var y = void 0; - var width = void 0; - var height = void 0; - - if (axis.isHorizontal()) { - x = prev; - y = gridRect.y; - width = tickCoord - x; - height = gridRect.height; - prev = x + width; - } else { - x = gridRect.x; - y = prev; - width = gridRect.width; - height = tickCoord - y; - prev = y + height; - } - - var tickValue = ticksCoords[i - 1].tickValue; - tickValue != null && newSplitAreaColors.set(tickValue, colorIndex); - axisGroup.add(new Rect({ - anid: tickValue != null ? 'area_' + tickValue : null, - shape: { - x: x, - y: y, - width: width, - height: height - }, - style: defaults({ - fill: areaColors[colorIndex] - }, areaStyle), - autoBatch: true, - silent: true - })); - colorIndex = (colorIndex + 1) % areaColorsLen; - } - - inner$3(axisView).splitAreaColors = newSplitAreaColors; - } - - function rectCoordAxisHandleRemove(axisView) { - inner$3(axisView).splitAreaColors = null; - } - - var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName']; - var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine']; - - var CartesianAxisView = - /** @class */ - function (_super) { - __extends(CartesianAxisView, _super); - - function CartesianAxisView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = CartesianAxisView.type; - _this.axisPointerClass = 'CartesianAxisPointer'; - return _this; - } - /** - * @override - */ - - - CartesianAxisView.prototype.render = function (axisModel, ecModel, api, payload) { - this.group.removeAll(); - var oldAxisGroup = this._axisGroup; - this._axisGroup = new Group$2(); - this.group.add(this._axisGroup); - - if (!axisModel.get('show')) { - return; - } - - var gridModel = axisModel.getCoordSysModel(); - var layout$1 = layout(gridModel, axisModel); - var axisBuilder = new AxisBuilder(axisModel, extend({ - handleAutoShown: function (elementType) { - var cartesians = gridModel.coordinateSystem.getCartesians(); - - for (var i = 0; i < cartesians.length; i++) { - if (isIntervalOrLogScale(cartesians[i].getOtherAxis(axisModel.axis).scale)) { - // Still show axis tick or axisLine if other axis is value / log - return true; - } - } // Not show axisTick or axisLine if other axis is category / time - - - return false; - } - }, layout$1)); - each$4(axisBuilderAttrs, axisBuilder.add, axisBuilder); - - this._axisGroup.add(axisBuilder.getGroup()); - - each$4(selfBuilderAttrs, function (name) { - if (axisModel.get([name, 'show'])) { - axisElementBuilders[name](this, this._axisGroup, axisModel, gridModel); - } - }, this); // THIS is a special case for bar racing chart. - // Update the axis label from the natural initial layout to - // sorted layout should has no animation. - - var isInitialSortFromBarRacing = payload && payload.type === 'changeAxisOrder' && payload.isInitSort; - - if (!isInitialSortFromBarRacing) { - groupTransition(oldAxisGroup, this._axisGroup, axisModel); - } - - _super.prototype.render.call(this, axisModel, ecModel, api, payload); - }; - - CartesianAxisView.prototype.remove = function () { - rectCoordAxisHandleRemove(this); - }; - - CartesianAxisView.type = 'cartesianAxis'; - return CartesianAxisView; - }(AxisView); - - var axisElementBuilders = { - splitLine: function (axisView, axisGroup, axisModel, gridModel) { - var axis = axisModel.axis; - - if (axis.scale.isBlank()) { - return; - } - - var splitLineModel = axisModel.getModel('splitLine'); - var lineStyleModel = splitLineModel.getModel('lineStyle'); - var lineColors = lineStyleModel.get('color'); - lineColors = isArray(lineColors) ? lineColors : [lineColors]; - var gridRect = gridModel.coordinateSystem.getRect(); - var isHorizontal = axis.isHorizontal(); - var lineCount = 0; - var ticksCoords = axis.getTicksCoords({ - tickModel: splitLineModel - }); - var p1 = []; - var p2 = []; - var lineStyle = lineStyleModel.getLineStyle(); - - for (var i = 0; i < ticksCoords.length; i++) { - var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); - - if (isHorizontal) { - p1[0] = tickCoord; - p1[1] = gridRect.y; - p2[0] = tickCoord; - p2[1] = gridRect.y + gridRect.height; - } else { - p1[0] = gridRect.x; - p1[1] = tickCoord; - p2[0] = gridRect.x + gridRect.width; - p2[1] = tickCoord; - } - - var colorIndex = lineCount++ % lineColors.length; - var tickValue = ticksCoords[i].tickValue; - var line = new Line({ - anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null, - autoBatch: true, - shape: { - x1: p1[0], - y1: p1[1], - x2: p2[0], - y2: p2[1] - }, - style: defaults({ - stroke: lineColors[colorIndex] - }, lineStyle), - silent: true - }); - subPixelOptimizeLine(line.shape, lineStyle.lineWidth); - axisGroup.add(line); - } - }, - minorSplitLine: function (axisView, axisGroup, axisModel, gridModel) { - var axis = axisModel.axis; - var minorSplitLineModel = axisModel.getModel('minorSplitLine'); - var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); - var gridRect = gridModel.coordinateSystem.getRect(); - var isHorizontal = axis.isHorizontal(); - var minorTicksCoords = axis.getMinorTicksCoords(); - - if (!minorTicksCoords.length) { - return; - } - - var p1 = []; - var p2 = []; - var lineStyle = lineStyleModel.getLineStyle(); - - for (var i = 0; i < minorTicksCoords.length; i++) { - for (var k = 0; k < minorTicksCoords[i].length; k++) { - var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord); - - if (isHorizontal) { - p1[0] = tickCoord; - p1[1] = gridRect.y; - p2[0] = tickCoord; - p2[1] = gridRect.y + gridRect.height; - } else { - p1[0] = gridRect.x; - p1[1] = tickCoord; - p2[0] = gridRect.x + gridRect.width; - p2[1] = tickCoord; - } - - var line = new Line({ - anid: 'minor_line_' + minorTicksCoords[i][k].tickValue, - autoBatch: true, - shape: { - x1: p1[0], - y1: p1[1], - x2: p2[0], - y2: p2[1] - }, - style: lineStyle, - silent: true - }); - subPixelOptimizeLine(line.shape, lineStyle.lineWidth); - axisGroup.add(line); - } - } - }, - splitArea: function (axisView, axisGroup, axisModel, gridModel) { - rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel); - } - }; - - var CartesianXAxisView = - /** @class */ - function (_super) { - __extends(CartesianXAxisView, _super); - - function CartesianXAxisView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = CartesianXAxisView.type; - return _this; - } - - CartesianXAxisView.type = 'xAxis'; - return CartesianXAxisView; - }(CartesianAxisView); - - var CartesianYAxisView = - /** @class */ - function (_super) { - __extends(CartesianYAxisView, _super); - - function CartesianYAxisView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = CartesianXAxisView.type; - return _this; - } - - CartesianYAxisView.type = 'yAxis'; - return CartesianYAxisView; - }(CartesianAxisView); // Grid view - - - var GridView = - /** @class */ - function (_super) { - __extends(GridView, _super); - - function GridView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = 'grid'; - return _this; - } - - GridView.prototype.render = function (gridModel, ecModel) { - this.group.removeAll(); - - if (gridModel.get('show')) { - this.group.add(new Rect({ - shape: gridModel.coordinateSystem.getRect(), - style: defaults({ - fill: gridModel.get('backgroundColor') - }, gridModel.getItemStyle()), - silent: true, - z2: -1 - })); - } - }; - - GridView.type = 'grid'; - return GridView; - }(ComponentView); - - var extraOption = { - // gridIndex: 0, - // gridId: '', - offset: 0 - }; - - function install$6(registers) { - registers.registerComponentView(GridView); - registers.registerComponentModel(GridModel); - registers.registerCoordinateSystem('cartesian2d', Grid); - axisModelCreator(registers, 'x', CartesianAxisModel, extraOption); - axisModelCreator(registers, 'y', CartesianAxisModel, extraOption); - registers.registerComponentView(CartesianXAxisView); - registers.registerComponentView(CartesianYAxisView); - registers.registerPreprocessor(function (option) { - // Only create grid when need - if (option.xAxis && option.yAxis && !option.grid) { - option.grid = {}; - } - }); - } - - use(install$6); - - var TitleModel = - /** @class */ - function (_super) { - __extends(TitleModel, _super); - - function TitleModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = TitleModel.type; - _this.layoutMode = { - type: 'box', - ignoreSize: true - }; - return _this; - } - - TitleModel.type = 'title'; - TitleModel.defaultOption = { - // zlevel: 0, - z: 6, - show: true, - text: '', - target: 'blank', - subtext: '', - subtarget: 'blank', - left: 0, - top: 0, - backgroundColor: 'rgba(0,0,0,0)', - borderColor: '#ccc', - borderWidth: 0, - padding: 5, - itemGap: 10, - textStyle: { - fontSize: 18, - fontWeight: 'bold', - color: '#464646' - }, - subtextStyle: { - fontSize: 12, - color: '#6E7079' - } - }; - return TitleModel; - }(ComponentModel); // View - - - var TitleView = - /** @class */ - function (_super) { - __extends(TitleView, _super); - - function TitleView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = TitleView.type; - return _this; - } - - TitleView.prototype.render = function (titleModel, ecModel, api) { - this.group.removeAll(); - - if (!titleModel.get('show')) { - return; - } - - var group = this.group; - var textStyleModel = titleModel.getModel('textStyle'); - var subtextStyleModel = titleModel.getModel('subtextStyle'); - var textAlign = titleModel.get('textAlign'); - var textVerticalAlign = retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign')); - var textEl = new ZRText({ - style: createTextStyle$1(textStyleModel, { - text: titleModel.get('text'), - fill: textStyleModel.getTextColor() - }, { - disableBox: true - }), - z2: 10 - }); - var textRect = textEl.getBoundingRect(); - var subText = titleModel.get('subtext'); - var subTextEl = new ZRText({ - style: createTextStyle$1(subtextStyleModel, { - text: subText, - fill: subtextStyleModel.getTextColor(), - y: textRect.height + titleModel.get('itemGap'), - verticalAlign: 'top' - }, { - disableBox: true - }), - z2: 10 - }); - var link = titleModel.get('link'); - var sublink = titleModel.get('sublink'); - var triggerEvent = titleModel.get('triggerEvent', true); - textEl.silent = !link && !triggerEvent; - subTextEl.silent = !sublink && !triggerEvent; - - if (link) { - textEl.on('click', function () { - windowOpen(link, '_' + titleModel.get('target')); - }); - } - - if (sublink) { - subTextEl.on('click', function () { - windowOpen(sublink, '_' + titleModel.get('subtarget')); - }); - } - - getECData(textEl).eventData = getECData(subTextEl).eventData = triggerEvent ? { - componentType: 'title', - componentIndex: titleModel.componentIndex - } : null; - group.add(textEl); - subText && group.add(subTextEl); // If no subText, but add subTextEl, there will be an empty line. - - var groupRect = group.getBoundingRect(); - var layoutOption = titleModel.getBoxLayoutParams(); - layoutOption.width = groupRect.width; - layoutOption.height = groupRect.height; - var layoutRect = getLayoutRect(layoutOption, { - width: api.getWidth(), - height: api.getHeight() - }, titleModel.get('padding')); // Adjust text align based on position - - if (!textAlign) { - // Align left if title is on the left. center and right is same - textAlign = titleModel.get('left') || titleModel.get('right'); // @ts-ignore - - if (textAlign === 'middle') { - textAlign = 'center'; - } // Adjust layout by text align - - - if (textAlign === 'right') { - layoutRect.x += layoutRect.width; - } else if (textAlign === 'center') { - layoutRect.x += layoutRect.width / 2; - } - } - - if (!textVerticalAlign) { - textVerticalAlign = titleModel.get('top') || titleModel.get('bottom'); // @ts-ignore - - if (textVerticalAlign === 'center') { - textVerticalAlign = 'middle'; - } - - if (textVerticalAlign === 'bottom') { - layoutRect.y += layoutRect.height; - } else if (textVerticalAlign === 'middle') { - layoutRect.y += layoutRect.height / 2; - } - - textVerticalAlign = textVerticalAlign || 'top'; - } - - group.x = layoutRect.x; - group.y = layoutRect.y; - group.markRedraw(); - var alignStyle = { - align: textAlign, - verticalAlign: textVerticalAlign - }; - textEl.setStyle(alignStyle); - subTextEl.setStyle(alignStyle); // Render background - // Get groupRect again because textAlign has been changed - - groupRect = group.getBoundingRect(); - var padding = layoutRect.margin; - var style = titleModel.getItemStyle(['color', 'opacity']); - style.fill = titleModel.get('backgroundColor'); - var rect = new Rect({ - shape: { - x: groupRect.x - padding[3], - y: groupRect.y - padding[0], - width: groupRect.width + padding[1] + padding[3], - height: groupRect.height + padding[0] + padding[2], - r: titleModel.get('borderRadius') - }, - style: style, - subPixelOptimize: true, - silent: true - }); - group.add(rect); - }; - - TitleView.type = 'title'; - return TitleView; - }(ComponentView); - - function install$5(registers) { - registers.registerComponentModel(TitleModel); - registers.registerComponentView(TitleView); - } - - use(install$5); - - var getDefaultSelectorOptions = function (ecModel, type) { - if (type === 'all') { - return { - type: 'all', - title: ecModel.getLocaleModel().get(['legend', 'selector', 'all']) - }; - } else if (type === 'inverse') { - return { - type: 'inverse', - title: ecModel.getLocaleModel().get(['legend', 'selector', 'inverse']) - }; - } - }; - - var LegendModel = - /** @class */ - function (_super) { - __extends(LegendModel, _super); - - function LegendModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = LegendModel.type; - _this.layoutMode = { - type: 'box', - // legend.width/height are maxWidth/maxHeight actually, - // whereas real width/height is calculated by its content. - // (Setting {left: 10, right: 10} does not make sense). - // So consider the case: - // `setOption({legend: {left: 10});` - // then `setOption({legend: {right: 10});` - // The previous `left` should be cleared by setting `ignoreSize`. - ignoreSize: true - }; - return _this; - } - - LegendModel.prototype.init = function (option, parentModel, ecModel) { - this.mergeDefaultAndTheme(option, ecModel); - option.selected = option.selected || {}; - - this._updateSelector(option); - }; - - LegendModel.prototype.mergeOption = function (option, ecModel) { - _super.prototype.mergeOption.call(this, option, ecModel); - - this._updateSelector(option); - }; - - LegendModel.prototype._updateSelector = function (option) { - var selector = option.selector; - var ecModel = this.ecModel; - - if (selector === true) { - selector = option.selector = ['all', 'inverse']; - } - - if (isArray(selector)) { - each$4(selector, function (item, index) { - isString(item) && (item = { - type: item - }); - selector[index] = merge(item, getDefaultSelectorOptions(ecModel, item.type)); - }); - } - }; - - LegendModel.prototype.optionUpdated = function () { - this._updateData(this.ecModel); - - var legendData = this._data; // If selectedMode is single, try to select one - - if (legendData[0] && this.get('selectedMode') === 'single') { - var hasSelected = false; // If has any selected in option.selected - - for (var i = 0; i < legendData.length; i++) { - var name_1 = legendData[i].get('name'); - - if (this.isSelected(name_1)) { - // Force to unselect others - this.select(name_1); - hasSelected = true; - break; - } - } // Try select the first if selectedMode is single - - - !hasSelected && this.select(legendData[0].get('name')); - } - }; - - LegendModel.prototype._updateData = function (ecModel) { - var potentialData = []; - var availableNames = []; - ecModel.eachRawSeries(function (seriesModel) { - var seriesName = seriesModel.name; - availableNames.push(seriesName); - var isPotential; - - if (seriesModel.legendVisualProvider) { - var provider = seriesModel.legendVisualProvider; - var names = provider.getAllNames(); - - if (!ecModel.isSeriesFiltered(seriesModel)) { - availableNames = availableNames.concat(names); - } - - if (names.length) { - potentialData = potentialData.concat(names); - } else { - isPotential = true; - } - } else { - isPotential = true; - } - - if (isPotential && isNameSpecified(seriesModel)) { - potentialData.push(seriesModel.name); - } - }); - /** - * @type {Array.} - * @private - */ - - this._availableNames = availableNames; // If legend.data is not specified in option, use availableNames as data, - // which is convenient for user preparing option. - - var rawData = this.get('data') || potentialData; - var legendNameMap = createHashMap(); - var legendData = map$1(rawData, function (dataItem) { - // Can be string or number - if (isString(dataItem) || isNumber(dataItem)) { - dataItem = { - name: dataItem - }; - } - - if (legendNameMap.get(dataItem.name)) { - // remove legend name duplicate - return null; - } - - legendNameMap.set(dataItem.name, true); - return new Model(dataItem, this, this.ecModel); - }, this); - /** - * @type {Array.} - * @private - */ - - this._data = filter(legendData, function (item) { - return !!item; - }); - }; - - LegendModel.prototype.getData = function () { - return this._data; - }; - - LegendModel.prototype.select = function (name) { - var selected = this.option.selected; - var selectedMode = this.get('selectedMode'); - - if (selectedMode === 'single') { - var data = this._data; - each$4(data, function (dataItem) { - selected[dataItem.get('name')] = false; - }); - } - - selected[name] = true; - }; - - LegendModel.prototype.unSelect = function (name) { - if (this.get('selectedMode') !== 'single') { - this.option.selected[name] = false; - } - }; - - LegendModel.prototype.toggleSelected = function (name) { - var selected = this.option.selected; // Default is true - - if (!selected.hasOwnProperty(name)) { - selected[name] = true; - } - - this[selected[name] ? 'unSelect' : 'select'](name); - }; - - LegendModel.prototype.allSelect = function () { - var data = this._data; - var selected = this.option.selected; - each$4(data, function (dataItem) { - selected[dataItem.get('name', true)] = true; - }); - }; - - LegendModel.prototype.inverseSelect = function () { - var data = this._data; - var selected = this.option.selected; - each$4(data, function (dataItem) { - var name = dataItem.get('name', true); // Initially, default value is true - - if (!selected.hasOwnProperty(name)) { - selected[name] = true; - } - - selected[name] = !selected[name]; - }); - }; - - LegendModel.prototype.isSelected = function (name) { - var selected = this.option.selected; - return !(selected.hasOwnProperty(name) && !selected[name]) && indexOf(this._availableNames, name) >= 0; - }; - - LegendModel.prototype.getOrient = function () { - return this.get('orient') === 'vertical' ? { - index: 1, - name: 'vertical' - } : { - index: 0, - name: 'horizontal' - }; - }; - - LegendModel.type = 'legend.plain'; - LegendModel.dependencies = ['series']; - LegendModel.defaultOption = { - // zlevel: 0, - z: 4, - show: true, - orient: 'horizontal', - left: 'center', - // right: 'center', - top: 0, - // bottom: null, - align: 'auto', - backgroundColor: 'rgba(0,0,0,0)', - borderColor: '#ccc', - borderRadius: 0, - borderWidth: 0, - padding: 5, - itemGap: 10, - itemWidth: 25, - itemHeight: 14, - symbolRotate: 'inherit', - symbolKeepAspect: true, - inactiveColor: '#ccc', - inactiveBorderColor: '#ccc', - inactiveBorderWidth: 'auto', - itemStyle: { - color: 'inherit', - opacity: 'inherit', - borderColor: 'inherit', - borderWidth: 'auto', - borderCap: 'inherit', - borderJoin: 'inherit', - borderDashOffset: 'inherit', - borderMiterLimit: 'inherit' - }, - lineStyle: { - width: 'auto', - color: 'inherit', - inactiveColor: '#ccc', - inactiveWidth: 2, - opacity: 'inherit', - type: 'inherit', - cap: 'inherit', - join: 'inherit', - dashOffset: 'inherit', - miterLimit: 'inherit' - }, - textStyle: { - color: '#333' - }, - selectedMode: true, - selector: false, - selectorLabel: { - show: true, - borderRadius: 10, - padding: [3, 5, 3, 5], - fontSize: 12, - fontFamily: 'sans-serif', - color: '#666', - borderWidth: 1, - borderColor: '#666' - }, - emphasis: { - selectorLabel: { - show: true, - color: '#eee', - backgroundColor: '#666' - } - }, - selectorPosition: 'auto', - selectorItemGap: 7, - selectorButtonGap: 10, - tooltip: { - show: false - } - }; - return LegendModel; - }(ComponentModel); - - function makeBackground(rect, componentModel) { - var padding = normalizeCssArray(componentModel.get('padding')); - var style = componentModel.getItemStyle(['color', 'opacity']); - style.fill = componentModel.get('backgroundColor'); - rect = new Rect({ - shape: { - x: rect.x - padding[3], - y: rect.y - padding[0], - width: rect.width + padding[1] + padding[3], - height: rect.height + padding[0] + padding[2], - r: componentModel.get('borderRadius') - }, - style: style, - silent: true, - z2: -1 - }); // FIXME - // `subPixelOptimizeRect` may bring some gap between edge of viewpart - // and background rect when setting like `left: 0`, `top: 0`. - // graphic.subPixelOptimizeRect(rect); - - return rect; - } - - var curry = curry$1; - var each$1 = each$4; - var Group$1 = Group$2; - - var LegendView = - /** @class */ - function (_super) { - __extends(LegendView, _super); - - function LegendView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = LegendView.type; - _this.newlineDisabled = false; - return _this; - } - - LegendView.prototype.init = function () { - this.group.add(this._contentGroup = new Group$1()); - this.group.add(this._selectorGroup = new Group$1()); - this._isFirstRender = true; - }; - /** - * @protected - */ - - - LegendView.prototype.getContentGroup = function () { - return this._contentGroup; - }; - /** - * @protected - */ - - - LegendView.prototype.getSelectorGroup = function () { - return this._selectorGroup; - }; - /** - * @override - */ - - - LegendView.prototype.render = function (legendModel, ecModel, api) { - var isFirstRender = this._isFirstRender; - this._isFirstRender = false; - this.resetInner(); - - if (!legendModel.get('show', true)) { - return; - } - - var itemAlign = legendModel.get('align'); - var orient = legendModel.get('orient'); - - if (!itemAlign || itemAlign === 'auto') { - itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left'; - } // selector has been normalized to an array in model - - - var selector = legendModel.get('selector', true); - var selectorPosition = legendModel.get('selectorPosition', true); - - if (selector && (!selectorPosition || selectorPosition === 'auto')) { - selectorPosition = orient === 'horizontal' ? 'end' : 'start'; - } - - this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); // Perform layout. - - var positionInfo = legendModel.getBoxLayoutParams(); - var viewportSize = { - width: api.getWidth(), - height: api.getHeight() - }; - var padding = legendModel.get('padding'); - var maxSize = getLayoutRect(positionInfo, viewportSize, padding); - var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition); // Place mainGroup, based on the calculated `mainRect`. - - var layoutRect = getLayoutRect(defaults({ - width: mainRect.width, - height: mainRect.height - }, positionInfo), viewportSize, padding); - this.group.x = layoutRect.x - mainRect.x; - this.group.y = layoutRect.y - mainRect.y; - this.group.markRedraw(); // Render background after group is layout. - - this.group.add(this._backgroundEl = makeBackground(mainRect, legendModel)); - }; - - LegendView.prototype.resetInner = function () { - this.getContentGroup().removeAll(); - this._backgroundEl && this.group.remove(this._backgroundEl); - this.getSelectorGroup().removeAll(); - }; - - LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { - var contentGroup = this.getContentGroup(); - var legendDrawnMap = createHashMap(); - var selectMode = legendModel.get('selectedMode'); - var excludeSeriesId = []; - ecModel.eachRawSeries(function (seriesModel) { - !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id); - }); - each$1(legendModel.getData(), function (legendItemModel, dataIndex) { - var name = legendItemModel.get('name'); // Use empty string or \n as a newline string - - if (!this.newlineDisabled && (name === '' || name === '\n')) { - var g = new Group$1(); // @ts-ignore - - g.newline = true; - contentGroup.add(g); - return; - } // Representitive series. - - - var seriesModel = ecModel.getSeriesByName(name)[0]; - - if (legendDrawnMap.get(name)) { - // Have been drawn - return; - } // Legend to control series. - - - if (seriesModel) { - var data = seriesModel.getData(); - var lineVisualStyle = data.getVisual('legendLineStyle') || {}; - var legendIcon = data.getVisual('legendIcon'); - /** - * `data.getVisual('style')` may be the color from the register - * in series. For example, for line series, - */ - - var style = data.getVisual('style'); - - var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, style, legendIcon, selectMode, api); - - itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId)); - - if (ecModel.ssr) { - itemGroup.eachChild(function (child) { - var ecData = getECData(child); - ecData.seriesIndex = seriesModel.seriesIndex; - ecData.dataIndex = dataIndex; - ecData.ssrType = 'legend'; - }); - } - - legendDrawnMap.set(name, true); - } else { - // Legend to control data. In pie and funnel. - ecModel.eachRawSeries(function (seriesModel) { - // In case multiple series has same data name - if (legendDrawnMap.get(name)) { - return; - } - - if (seriesModel.legendVisualProvider) { - var provider = seriesModel.legendVisualProvider; - - if (!provider.containName(name)) { - return; - } - - var idx = provider.indexOfName(name); - var style = provider.getItemVisual(idx, 'style'); - var legendIcon = provider.getItemVisual(idx, 'legendIcon'); - var colorArr = parse(style.fill); // Color may be set to transparent in visualMap when data is out of range. - // Do not show nothing. - - if (colorArr && colorArr[3] === 0) { - colorArr[3] = 0.2; // TODO color is set to 0, 0, 0, 0. Should show correct RGBA - - style = extend(extend({}, style), { - fill: stringify(colorArr, 'rgba') - }); - } - - var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, {}, style, legendIcon, selectMode, api); // FIXME: consider different series has items with the same name. - - - itemGroup.on('click', curry(dispatchSelectAction, null, name, api, excludeSeriesId)) // Should not specify the series name, consider legend controls - // more than one pie series. - .on('mouseover', curry(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, null, name, api, excludeSeriesId)); - - if (ecModel.ssr) { - itemGroup.eachChild(function (child) { - var ecData = getECData(child); - ecData.seriesIndex = seriesModel.seriesIndex; - ecData.dataIndex = dataIndex; - ecData.ssrType = 'legend'; - }); - } - - legendDrawnMap.set(name, true); - } - }, this); - } - - { - if (!legendDrawnMap.get(name)) { - console.warn(name + ' series not exists. Legend data should be same with series name or data name.'); - } - } - }, this); - - if (selector) { - this._createSelector(selector, legendModel, api, orient, selectorPosition); - } - }; - - LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) { - var selectorGroup = this.getSelectorGroup(); - each$1(selector, function createSelectorButton(selectorItem) { - var type = selectorItem.type; - var labelText = new ZRText({ - style: { - x: 0, - y: 0, - align: 'center', - verticalAlign: 'middle' - }, - onclick: function () { - api.dispatchAction({ - type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect' - }); - } - }); - selectorGroup.add(labelText); - var labelModel = legendModel.getModel('selectorLabel'); - var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']); - setLabelStyle(labelText, { - normal: labelModel, - emphasis: emphasisLabelModel - }, { - defaultText: selectorItem.title - }); - enableHoverEmphasis(labelText); - }); - }; - - LegendView.prototype._createItem = function (seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, itemVisualStyle, legendIcon, selectMode, api) { - var drawType = seriesModel.visualDrawType; - var itemWidth = legendModel.get('itemWidth'); - var itemHeight = legendModel.get('itemHeight'); - var isSelected = legendModel.isSelected(name); - var iconRotate = legendItemModel.get('symbolRotate'); - var symbolKeepAspect = legendItemModel.get('symbolKeepAspect'); - var legendIconType = legendItemModel.get('icon'); - legendIcon = legendIconType || legendIcon || 'roundRect'; - var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api); - var itemGroup = new Group$1(); - var textStyleModel = legendItemModel.getModel('textStyle'); - - if (isFunction(seriesModel.getLegendIcon) && (!legendIconType || legendIconType === 'inherit')) { - // Series has specific way to define legend icon - itemGroup.add(seriesModel.getLegendIcon({ - itemWidth: itemWidth, - itemHeight: itemHeight, - icon: legendIcon, - iconRotate: iconRotate, - itemStyle: style.itemStyle, - lineStyle: style.lineStyle, - symbolKeepAspect: symbolKeepAspect - })); - } else { - // Use default legend icon policy for most series - var rotate = legendIconType === 'inherit' && seriesModel.getData().getVisual('symbol') ? iconRotate === 'inherit' ? seriesModel.getData().getVisual('symbolRotate') : iconRotate : 0; // No rotation for no icon - - itemGroup.add(getDefaultLegendIcon({ - itemWidth: itemWidth, - itemHeight: itemHeight, - icon: legendIcon, - iconRotate: rotate, - itemStyle: style.itemStyle, - lineStyle: style.lineStyle, - symbolKeepAspect: symbolKeepAspect - })); - } - - var textX = itemAlign === 'left' ? itemWidth + 5 : -5; - var textAlign = itemAlign; - var formatter = legendModel.get('formatter'); - var content = name; - - if (isString(formatter) && formatter) { - content = formatter.replace('{name}', name != null ? name : ''); - } else if (isFunction(formatter)) { - content = formatter(name); - } - - var textColor = isSelected ? textStyleModel.getTextColor() : legendItemModel.get('inactiveColor'); - itemGroup.add(new ZRText({ - style: createTextStyle$1(textStyleModel, { - text: content, - x: textX, - y: itemHeight / 2, - fill: textColor, - align: textAlign, - verticalAlign: 'middle' - }, { - inheritColor: textColor - }) - })); // Add a invisible rect to increase the area of mouse hover - - var hitRect = new Rect({ - shape: itemGroup.getBoundingRect(), - style: { - // Cannot use 'invisible' because SVG SSR will miss the node - fill: 'transparent' - } - }); - var tooltipModel = legendItemModel.getModel('tooltip'); - - if (tooltipModel.get('show')) { - setTooltipConfig({ - el: hitRect, - componentModel: legendModel, - itemName: name, - itemTooltipOption: tooltipModel.option - }); - } - - itemGroup.add(hitRect); - itemGroup.eachChild(function (child) { - child.silent = true; - }); - hitRect.silent = !selectMode; - this.getContentGroup().add(itemGroup); - enableHoverEmphasis(itemGroup); // @ts-ignore - - itemGroup.__legendDataIndex = dataIndex; - return itemGroup; - }; - - LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { - var contentGroup = this.getContentGroup(); - var selectorGroup = this.getSelectorGroup(); // Place items in contentGroup. - - box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height); - var contentRect = contentGroup.getBoundingRect(); - var contentPos = [-contentRect.x, -contentRect.y]; - selectorGroup.markRedraw(); - contentGroup.markRedraw(); - - if (selector) { - // Place buttons in selectorGroup - box( // Buttons in selectorGroup always layout horizontally - 'horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); - var selectorRect = selectorGroup.getBoundingRect(); - var selectorPos = [-selectorRect.x, -selectorRect.y]; - var selectorButtonGap = legendModel.get('selectorButtonGap', true); - var orientIdx = legendModel.getOrient().index; - var wh = orientIdx === 0 ? 'width' : 'height'; - var hw = orientIdx === 0 ? 'height' : 'width'; - var yx = orientIdx === 0 ? 'y' : 'x'; - - if (selectorPosition === 'end') { - selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap; - } else { - contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap; - } // Always align selector to content as 'middle' - - - selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2; - selectorGroup.x = selectorPos[0]; - selectorGroup.y = selectorPos[1]; - contentGroup.x = contentPos[0]; - contentGroup.y = contentPos[1]; - var mainRect = { - x: 0, - y: 0 - }; - mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh]; - mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]); - mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]); - return mainRect; - } else { - contentGroup.x = contentPos[0]; - contentGroup.y = contentPos[1]; - return this.group.getBoundingRect(); - } - }; - /** - * @protected - */ - - - LegendView.prototype.remove = function () { - this.getContentGroup().removeAll(); - this._isFirstRender = true; - }; - - LegendView.type = 'legend.plain'; - return LegendView; - }(ComponentView); - - function getLegendStyle(iconType, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api) { - /** - * Use series style if is inherit; - * elsewise, use legend style - */ - function handleCommonProps(style, visualStyle) { - // If lineStyle.width is 'auto', it is set to be 2 if series has border - if (style.lineWidth === 'auto') { - style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0; - } - - each$1(style, function (propVal, propName) { - style[propName] === 'inherit' && (style[propName] = visualStyle[propName]); - }); - } // itemStyle - - - var itemStyleModel = legendItemModel.getModel('itemStyle'); - var itemStyle = itemStyleModel.getItemStyle(); - var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke'; - var decalStyle = itemStyleModel.getShallow('decal'); - itemStyle.decal = !decalStyle || decalStyle === 'inherit' ? itemVisualStyle.decal : createOrUpdatePatternFromDecal(decalStyle, api); - - if (itemStyle.fill === 'inherit') { - /** - * Series with visualDrawType as 'stroke' should have - * series stroke as legend fill - */ - itemStyle.fill = itemVisualStyle[drawType]; - } - - if (itemStyle.stroke === 'inherit') { - /** - * icon type with "emptyXXX" should use fill color - * in visual style - */ - itemStyle.stroke = itemVisualStyle[iconBrushType]; - } - - if (itemStyle.opacity === 'inherit') { - /** - * Use lineStyle.opacity if drawType is stroke - */ - itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity; - } - - handleCommonProps(itemStyle, itemVisualStyle); // lineStyle - - var legendLineModel = legendItemModel.getModel('lineStyle'); - var lineStyle = legendLineModel.getLineStyle(); - handleCommonProps(lineStyle, lineVisualStyle); // Fix auto color to real color - - itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill); - itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill); - lineStyle.stroke === 'auto' && (lineStyle.stroke = itemVisualStyle.fill); - - if (!isSelected) { - var borderWidth = legendItemModel.get('inactiveBorderWidth'); - /** - * Since stroke is set to be inactiveBorderColor, it may occur that - * there is no border in series but border in legend, so we need to - * use border only when series has border if is set to be auto - */ - - var visualHasBorder = itemStyle[iconBrushType]; - itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth; - itemStyle.fill = legendItemModel.get('inactiveColor'); - itemStyle.stroke = legendItemModel.get('inactiveBorderColor'); - lineStyle.stroke = legendLineModel.get('inactiveColor'); - lineStyle.lineWidth = legendLineModel.get('inactiveWidth'); - } - - return { - itemStyle: itemStyle, - lineStyle: lineStyle - }; - } - - function getDefaultLegendIcon(opt) { - var symboType = opt.icon || 'roundRect'; - var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect); - icon.setStyle(opt.itemStyle); - icon.rotation = (opt.iconRotate || 0) * Math.PI / 180; - icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]); - - if (symboType.indexOf('empty') > -1) { - icon.style.stroke = icon.style.fill; - icon.style.fill = '#fff'; - icon.style.lineWidth = 2; - } - - return icon; - } - - function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) { - // downplay before unselect - dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId); - api.dispatchAction({ - type: 'legendToggleSelect', - name: seriesName != null ? seriesName : dataName - }); // highlight after select - // TODO highlight immediately may cause animation loss. - - dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId); - } - - function isUseHoverLayer(api) { - var list = api.getZr().storage.getDisplayList(); - var emphasisState; - var i = 0; - var len = list.length; - - while (i < len && !(emphasisState = list[i].states.emphasis)) { - i++; - } - - return emphasisState && emphasisState.hoverLayer; - } - - function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) { - // If element hover will move to a hoverLayer. - if (!isUseHoverLayer(api)) { - api.dispatchAction({ - type: 'highlight', - seriesName: seriesName, - name: dataName, - excludeSeriesId: excludeSeriesId - }); - } - } - - function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) { - // If element hover will move to a hoverLayer. - if (!isUseHoverLayer(api)) { - api.dispatchAction({ - type: 'downplay', - seriesName: seriesName, - name: dataName, - excludeSeriesId: excludeSeriesId - }); - } - } - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - function legendFilter(ecModel) { - var legendModels = ecModel.findComponents({ - mainType: 'legend' - }); - - if (legendModels && legendModels.length) { - ecModel.filterSeries(function (series) { - // If in any legend component the status is not selected. - // Because in legend series is assumed selected when it is not in the legend data. - for (var i = 0; i < legendModels.length; i++) { - if (!legendModels[i].isSelected(series.name)) { - return false; - } - } - - return true; - }); - } - } - - function legendSelectActionHandler(methodName, payload, ecModel) { - var selectedMap = {}; - var isToggleSelect = methodName === 'toggleSelected'; - var isSelected; // Update all legend components - - ecModel.eachComponent('legend', function (legendModel) { - if (isToggleSelect && isSelected != null) { - // Force other legend has same selected status - // Or the first is toggled to true and other are toggled to false - // In the case one legend has some item unSelected in option. And if other legend - // doesn't has the item, they will assume it is selected. - legendModel[isSelected ? 'select' : 'unSelect'](payload.name); - } else if (methodName === 'allSelect' || methodName === 'inverseSelect') { - legendModel[methodName](); - } else { - legendModel[methodName](payload.name); - isSelected = legendModel.isSelected(payload.name); - } - - var legendData = legendModel.getData(); - each$4(legendData, function (model) { - var name = model.get('name'); // Wrap element - - if (name === '\n' || name === '') { - return; - } - - var isItemSelected = legendModel.isSelected(name); - - if (selectedMap.hasOwnProperty(name)) { - // Unselected if any legend is unselected - selectedMap[name] = selectedMap[name] && isItemSelected; - } else { - selectedMap[name] = isItemSelected; - } - }); - }); // Return the event explicitly - - return methodName === 'allSelect' || methodName === 'inverseSelect' ? { - selected: selectedMap - } : { - name: payload.name, - selected: selectedMap - }; - } - - function installLegendAction(registers) { - /** - * @event legendToggleSelect - * @type {Object} - * @property {string} type 'legendToggleSelect' - * @property {string} [from] - * @property {string} name Series name or data item name - */ - registers.registerAction('legendToggleSelect', 'legendselectchanged', curry$1(legendSelectActionHandler, 'toggleSelected')); - registers.registerAction('legendAllSelect', 'legendselectall', curry$1(legendSelectActionHandler, 'allSelect')); - registers.registerAction('legendInverseSelect', 'legendinverseselect', curry$1(legendSelectActionHandler, 'inverseSelect')); - /** - * @event legendSelect - * @type {Object} - * @property {string} type 'legendSelect' - * @property {string} name Series name or data item name - */ - - registers.registerAction('legendSelect', 'legendselected', curry$1(legendSelectActionHandler, 'select')); - /** - * @event legendUnSelect - * @type {Object} - * @property {string} type 'legendUnSelect' - * @property {string} name Series name or data item name - */ - - registers.registerAction('legendUnSelect', 'legendunselected', curry$1(legendSelectActionHandler, 'unSelect')); - } - - function install$4(registers) { - registers.registerComponentModel(LegendModel); - registers.registerComponentView(LegendView); - registers.registerProcessor(registers.PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter); - registers.registerSubTypeDefaulter('legend', function () { - return 'plain'; - }); - installLegendAction(registers); - } - - var ScrollableLegendModel = - /** @class */ - function (_super) { - __extends(ScrollableLegendModel, _super); - - function ScrollableLegendModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = ScrollableLegendModel.type; - return _this; - } - /** - * @param {number} scrollDataIndex - */ - - - ScrollableLegendModel.prototype.setScrollDataIndex = function (scrollDataIndex) { - this.option.scrollDataIndex = scrollDataIndex; - }; - - ScrollableLegendModel.prototype.init = function (option, parentModel, ecModel) { - var inputPositionParams = getLayoutParams(option); - - _super.prototype.init.call(this, option, parentModel, ecModel); - - mergeAndNormalizeLayoutParams(this, option, inputPositionParams); - }; - /** - * @override - */ - - - ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) { - _super.prototype.mergeOption.call(this, option, ecModel); - - mergeAndNormalizeLayoutParams(this, this.option, option); - }; - - ScrollableLegendModel.type = 'legend.scroll'; - ScrollableLegendModel.defaultOption = inheritDefaultOption(LegendModel.defaultOption, { - scrollDataIndex: 0, - pageButtonItemGap: 5, - pageButtonGap: null, - pageButtonPosition: 'end', - pageFormatter: '{current}/{total}', - pageIcons: { - horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'], - vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z'] - }, - pageIconColor: '#2f4554', - pageIconInactiveColor: '#aaa', - pageIconSize: 15, - pageTextStyle: { - color: '#333' - }, - animationDurationUpdate: 800 - }); - return ScrollableLegendModel; - }(LegendModel); // Do not `ignoreSize` to enable setting {left: 10, right: 10}. - - - function mergeAndNormalizeLayoutParams(legendModel, target, raw) { - var orient = legendModel.getOrient(); - var ignoreSize = [1, 1]; - ignoreSize[orient.index] = 0; - mergeLayoutParam(target, raw, { - type: 'box', - ignoreSize: !!ignoreSize - }); - } - - var Group = Group$2; - var WH = ['width', 'height']; - var XY = ['x', 'y']; - - var ScrollableLegendView = - /** @class */ - function (_super) { - __extends(ScrollableLegendView, _super); - - function ScrollableLegendView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = ScrollableLegendView.type; - _this.newlineDisabled = true; - _this._currentIndex = 0; - return _this; - } - - ScrollableLegendView.prototype.init = function () { - _super.prototype.init.call(this); - - this.group.add(this._containerGroup = new Group()); - - this._containerGroup.add(this.getContentGroup()); - - this.group.add(this._controllerGroup = new Group()); - }; - /** - * @override - */ - - - ScrollableLegendView.prototype.resetInner = function () { - _super.prototype.resetInner.call(this); - - this._controllerGroup.removeAll(); - - this._containerGroup.removeClipPath(); - - this._containerGroup.__rectSize = null; - }; - /** - * @override - */ - - - ScrollableLegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { - var self = this; // Render content items. - - _super.prototype.renderInner.call(this, itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); - - var controllerGroup = this._controllerGroup; // FIXME: support be 'auto' adapt to size number text length, - // e.g., '3/12345' should not overlap with the control arrow button. - - var pageIconSize = legendModel.get('pageIconSize', true); - var pageIconSizeArr = isArray(pageIconSize) ? pageIconSize : [pageIconSize, pageIconSize]; - createPageButton('pagePrev', 0); - var pageTextStyleModel = legendModel.getModel('pageTextStyle'); - controllerGroup.add(new ZRText({ - name: 'pageText', - style: { - // Placeholder to calculate a proper layout. - text: 'xx/xx', - fill: pageTextStyleModel.getTextColor(), - font: pageTextStyleModel.getFont(), - verticalAlign: 'middle', - align: 'center' - }, - silent: true - })); - createPageButton('pageNext', 1); - - function createPageButton(name, iconIdx) { - var pageDataIndexName = name + 'DataIndex'; - var icon = createIcon(legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], { - // Buttons will be created in each render, so we do not need - // to worry about avoiding using legendModel kept in scope. - onclick: bind$1(self._pageGo, self, pageDataIndexName, legendModel, api) - }, { - x: -pageIconSizeArr[0] / 2, - y: -pageIconSizeArr[1] / 2, - width: pageIconSizeArr[0], - height: pageIconSizeArr[1] - }); - icon.name = name; - controllerGroup.add(icon); - } - }; - /** - * @override - */ - - - ScrollableLegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { - var selectorGroup = this.getSelectorGroup(); - var orientIdx = legendModel.getOrient().index; - var wh = WH[orientIdx]; - var xy = XY[orientIdx]; - var hw = WH[1 - orientIdx]; - var yx = XY[1 - orientIdx]; - selector && box( // Buttons in selectorGroup always layout horizontally - 'horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); - var selectorButtonGap = legendModel.get('selectorButtonGap', true); - var selectorRect = selectorGroup.getBoundingRect(); - var selectorPos = [-selectorRect.x, -selectorRect.y]; - var processMaxSize = clone$3(maxSize); - selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap); - - var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx, xy); - - if (selector) { - if (selectorPosition === 'end') { - selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap; - } else { - var offset = selectorRect[wh] + selectorButtonGap; - selectorPos[orientIdx] -= offset; - mainRect[xy] -= offset; - } - - mainRect[wh] += selectorRect[wh] + selectorButtonGap; - selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2; - mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]); - mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]); - selectorGroup.x = selectorPos[0]; - selectorGroup.y = selectorPos[1]; - selectorGroup.markRedraw(); - } - - return mainRect; - }; - - ScrollableLegendView.prototype._layoutContentAndController = function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx, xy) { - var contentGroup = this.getContentGroup(); - var containerGroup = this._containerGroup; - var controllerGroup = this._controllerGroup; // Place items in contentGroup. - - box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height); - box( // Buttons in controller are layout always horizontally. - 'horizontal', controllerGroup, legendModel.get('pageButtonItemGap', true)); - var contentRect = contentGroup.getBoundingRect(); - var controllerRect = controllerGroup.getBoundingRect(); - var showController = this._showController = contentRect[wh] > maxSize[wh]; // In case that the inner elements of contentGroup layout do not based on [0, 0] - - var contentPos = [-contentRect.x, -contentRect.y]; // Remain contentPos when scroll animation perfroming. - // If first rendering, `contentGroup.position` is [0, 0], which - // does not make sense and may cause unexepcted animation if adopted. - - if (!isFirstRender) { - contentPos[orientIdx] = contentGroup[xy]; - } // Layout container group based on 0. - - - var containerPos = [0, 0]; - var controllerPos = [-controllerRect.x, -controllerRect.y]; - var pageButtonGap = retrieve2(legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true)); // Place containerGroup and controllerGroup and contentGroup. - - if (showController) { - var pageButtonPosition = legendModel.get('pageButtonPosition', true); // controller is on the right / bottom. - - if (pageButtonPosition === 'end') { - controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh]; - } // controller is on the left / top. - else { - containerPos[orientIdx] += controllerRect[wh] + pageButtonGap; - } - } // Always align controller to content as 'middle'. - - - controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2; - contentGroup.setPosition(contentPos); - containerGroup.setPosition(containerPos); - controllerGroup.setPosition(controllerPos); // Calculate `mainRect` and set `clipPath`. - // mainRect should not be calculated by `this.group.getBoundingRect()` - // for sake of the overflow. - - var mainRect = { - x: 0, - y: 0 - }; // Consider content may be overflow (should be clipped). - - mainRect[wh] = showController ? maxSize[wh] : contentRect[wh]; - mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]); // `containerRect[yx] + containerPos[1 - orientIdx]` is 0. - - mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]); - containerGroup.__rectSize = maxSize[wh]; - - if (showController) { - var clipShape = { - x: 0, - y: 0 - }; - clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0); - clipShape[hw] = mainRect[hw]; - containerGroup.setClipPath(new Rect({ - shape: clipShape - })); // Consider content may be larger than container, container rect - // can not be obtained from `containerGroup.getBoundingRect()`. - - containerGroup.__rectSize = clipShape[wh]; - } else { - // Do not remove or ignore controller. Keep them set as placeholders. - controllerGroup.eachChild(function (child) { - child.attr({ - invisible: true, - silent: true - }); - }); - } // Content translate animation. - - - var pageInfo = this._getPageInfo(legendModel); - - pageInfo.pageIndex != null && updateProps$1(contentGroup, { - x: pageInfo.contentPosition[0], - y: pageInfo.contentPosition[1] - }, // When switch from "show controller" to "not show controller", view should be - // updated immediately without animation, otherwise causes weird effect. - showController ? legendModel : null); - - this._updatePageInfoView(legendModel, pageInfo); - - return mainRect; - }; - - ScrollableLegendView.prototype._pageGo = function (to, legendModel, api) { - var scrollDataIndex = this._getPageInfo(legendModel)[to]; - - scrollDataIndex != null && api.dispatchAction({ - type: 'legendScroll', - scrollDataIndex: scrollDataIndex, - legendId: legendModel.id - }); - }; - - ScrollableLegendView.prototype._updatePageInfoView = function (legendModel, pageInfo) { - var controllerGroup = this._controllerGroup; - each$4(['pagePrev', 'pageNext'], function (name) { - var key = name + 'DataIndex'; - var canJump = pageInfo[key] != null; - var icon = controllerGroup.childOfName(name); - - if (icon) { - icon.setStyle('fill', canJump ? legendModel.get('pageIconColor', true) : legendModel.get('pageIconInactiveColor', true)); - icon.cursor = canJump ? 'pointer' : 'default'; - } - }); - var pageText = controllerGroup.childOfName('pageText'); - var pageFormatter = legendModel.get('pageFormatter'); - var pageIndex = pageInfo.pageIndex; - var current = pageIndex != null ? pageIndex + 1 : 0; - var total = pageInfo.pageCount; - pageText && pageFormatter && pageText.setStyle('text', isString(pageFormatter) ? pageFormatter.replace('{current}', current == null ? '' : current + '').replace('{total}', total == null ? '' : total + '') : pageFormatter({ - current: current, - total: total - })); - }; - /** - * contentPosition: Array., null when data item not found. - * pageIndex: number, null when data item not found. - * pageCount: number, always be a number, can be 0. - * pagePrevDataIndex: number, null when no previous page. - * pageNextDataIndex: number, null when no next page. - * } - */ - - - ScrollableLegendView.prototype._getPageInfo = function (legendModel) { - var scrollDataIndex = legendModel.get('scrollDataIndex', true); - var contentGroup = this.getContentGroup(); - var containerRectSize = this._containerGroup.__rectSize; - var orientIdx = legendModel.getOrient().index; - var wh = WH[orientIdx]; - var xy = XY[orientIdx]; - - var targetItemIndex = this._findTargetItemIndex(scrollDataIndex); - - var children = contentGroup.children(); - var targetItem = children[targetItemIndex]; - var itemCount = children.length; - var pCount = !itemCount ? 0 : 1; - var result = { - contentPosition: [contentGroup.x, contentGroup.y], - pageCount: pCount, - pageIndex: pCount - 1, - pagePrevDataIndex: null, - pageNextDataIndex: null - }; - - if (!targetItem) { - return result; - } - - var targetItemInfo = getItemInfo(targetItem); - result.contentPosition[orientIdx] = -targetItemInfo.s; // Strategy: - // (1) Always align based on the left/top most item. - // (2) It is user-friendly that the last item shown in the - // current window is shown at the begining of next window. - // Otherwise if half of the last item is cut by the window, - // it will have no chance to display entirely. - // (3) Consider that item size probably be different, we - // have calculate pageIndex by size rather than item index, - // and we can not get page index directly by division. - // (4) The window is to narrow to contain more than - // one item, we should make sure that the page can be fliped. - - for (var i = targetItemIndex + 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i <= itemCount; ++i) { - currItemInfo = getItemInfo(children[i]); - - if ( // Half of the last item is out of the window. - !currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize // If the current item does not intersect with the window, the new page - // can be started at the current item or the last item. - || currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) { - if (winEndItemInfo.i > winStartItemInfo.i) { - winStartItemInfo = winEndItemInfo; - } else { - // e.g., when page size is smaller than item size. - winStartItemInfo = currItemInfo; - } - - if (winStartItemInfo) { - if (result.pageNextDataIndex == null) { - result.pageNextDataIndex = winStartItemInfo.i; - } - - ++result.pageCount; - } - } - - winEndItemInfo = currItemInfo; - } - - for (var i = targetItemIndex - 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i >= -1; --i) { - currItemInfo = getItemInfo(children[i]); - - if ( // If the the end item does not intersect with the window started - // from the current item, a page can be settled. - (!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s) // e.g., when page size is smaller than item size. - ) && winStartItemInfo.i < winEndItemInfo.i) { - winEndItemInfo = winStartItemInfo; - - if (result.pagePrevDataIndex == null) { - result.pagePrevDataIndex = winStartItemInfo.i; - } - - ++result.pageCount; - ++result.pageIndex; - } - - winStartItemInfo = currItemInfo; - } - - return result; - - function getItemInfo(el) { - if (el) { - var itemRect = el.getBoundingRect(); - var start = itemRect[xy] + el[xy]; - return { - s: start, - e: start + itemRect[wh], - i: el.__legendDataIndex - }; - } - } - - function intersect(itemInfo, winStart) { - return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize; - } - }; - - ScrollableLegendView.prototype._findTargetItemIndex = function (targetDataIndex) { - if (!this._showController) { - return 0; - } - - var index; - var contentGroup = this.getContentGroup(); - var defaultIndex; - contentGroup.eachChild(function (child, idx) { - var legendDataIdx = child.__legendDataIndex; // FIXME - // If the given targetDataIndex (from model) is illegal, - // we use defaultIndex. But the index on the legend model and - // action payload is still illegal. That case will not be - // changed until some scenario requires. - - if (defaultIndex == null && legendDataIdx != null) { - defaultIndex = idx; - } - - if (legendDataIdx === targetDataIndex) { - index = idx; - } - }); - return index != null ? index : defaultIndex; - }; - - ScrollableLegendView.type = 'legend.scroll'; - return ScrollableLegendView; - }(LegendView); - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - /** - * AUTO-GENERATED FILE. DO NOT MODIFY. - */ - - /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - function installScrollableLegendAction(registers) { - /** - * @event legendScroll - * @type {Object} - * @property {string} type 'legendScroll' - * @property {string} scrollDataIndex - */ - registers.registerAction('legendScroll', 'legendscroll', function (payload, ecModel) { - var scrollDataIndex = payload.scrollDataIndex; - scrollDataIndex != null && ecModel.eachComponent({ - mainType: 'legend', - subType: 'scroll', - query: payload - }, function (legendModel) { - legendModel.setScrollDataIndex(scrollDataIndex); - }); - }); - } - - function install$3(registers) { - use(install$4); - registers.registerComponentModel(ScrollableLegendModel); - registers.registerComponentView(ScrollableLegendView); - installScrollableLegendAction(registers); - } - - use(install$3); - var inner$2 = makeInner(); - var clone = clone$3; - var bind = bind$1; - /** - * Base axis pointer class in 2D. - */ - - var BaseAxisPointer = - /** @class */ - function () { - function BaseAxisPointer() { - this._dragging = false; - /** - * In px, arbitrary value. Do not set too small, - * no animation is ok for most cases. - */ - - this.animationThreshold = 15; - } - /** - * @implement - */ - - - BaseAxisPointer.prototype.render = function (axisModel, axisPointerModel, api, forceRender) { - var value = axisPointerModel.get('value'); - var status = axisPointerModel.get('status'); // Bind them to `this`, not in closure, otherwise they will not - // be replaced when user calling setOption in not merge mode. - - this._axisModel = axisModel; - this._axisPointerModel = axisPointerModel; - this._api = api; // Optimize: `render` will be called repeatedly during mouse move. - // So it is power consuming if performing `render` each time, - // especially on mobile device. - - if (!forceRender && this._lastValue === value && this._lastStatus === status) { - return; - } - - this._lastValue = value; - this._lastStatus = status; - var group = this._group; - var handle = this._handle; - - if (!status || status === 'hide') { - // Do not clear here, for animation better. - group && group.hide(); - handle && handle.hide(); - return; - } - - group && group.show(); - handle && handle.show(); // Otherwise status is 'show' - - var elOption = {}; - this.makeElOption(elOption, value, axisModel, axisPointerModel, api); // Enable change axis pointer type. - - var graphicKey = elOption.graphicKey; - - if (graphicKey !== this._lastGraphicKey) { - this.clear(api); - } - - this._lastGraphicKey = graphicKey; - var moveAnimation = this._moveAnimation = this.determineAnimation(axisModel, axisPointerModel); - - if (!group) { - group = this._group = new Group$2(); - this.createPointerEl(group, elOption, axisModel, axisPointerModel); - this.createLabelEl(group, elOption, axisModel, axisPointerModel); - api.getZr().add(group); - } else { - var doUpdateProps = curry$1(updateProps, axisPointerModel, moveAnimation); - this.updatePointerEl(group, elOption, doUpdateProps); - this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel); - } - - updateMandatoryProps(group, axisPointerModel, true); - - this._renderHandle(value); - }; - /** - * @implement - */ - - - BaseAxisPointer.prototype.remove = function (api) { - this.clear(api); - }; - /** - * @implement - */ - - - BaseAxisPointer.prototype.dispose = function (api) { - this.clear(api); - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.determineAnimation = function (axisModel, axisPointerModel) { - var animation = axisPointerModel.get('animation'); - var axis = axisModel.axis; - var isCategoryAxis = axis.type === 'category'; - var useSnap = axisPointerModel.get('snap'); // Value axis without snap always do not snap. - - if (!useSnap && !isCategoryAxis) { - return false; - } - - if (animation === 'auto' || animation == null) { - var animationThreshold = this.animationThreshold; - - if (isCategoryAxis && axis.getBandWidth() > animationThreshold) { - return true; - } // It is important to auto animation when snap used. Consider if there is - // a dataZoom, animation will be disabled when too many points exist, while - // it will be enabled for better visual effect when little points exist. - - - if (useSnap) { - var seriesDataCount = getAxisInfo(axisModel).seriesDataCount; - var axisExtent = axis.getExtent(); // Approximate band width - - return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold; - } - - return false; - } - - return animation === true; - }; - /** - * add {pointer, label, graphicKey} to elOption - * @protected - */ - - - BaseAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {// Should be implemenented by sub-class. - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.createPointerEl = function (group, elOption, axisModel, axisPointerModel) { - var pointerOption = elOption.pointer; - - if (pointerOption) { - var pointerEl = inner$2(group).pointerEl = new graphic$1[pointerOption.type](clone(elOption.pointer)); - group.add(pointerEl); - } - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.createLabelEl = function (group, elOption, axisModel, axisPointerModel) { - if (elOption.label) { - var labelEl = inner$2(group).labelEl = new ZRText(clone(elOption.label)); - group.add(labelEl); - updateLabelShowHide(labelEl, axisPointerModel); - } - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) { - var pointerEl = inner$2(group).pointerEl; - - if (pointerEl && elOption.pointer) { - pointerEl.setStyle(elOption.pointer.style); - updateProps(pointerEl, { - shape: elOption.pointer.shape - }); - } - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.updateLabelEl = function (group, elOption, updateProps, axisPointerModel) { - var labelEl = inner$2(group).labelEl; - - if (labelEl) { - labelEl.setStyle(elOption.label.style); - updateProps(labelEl, { - // Consider text length change in vertical axis, animation should - // be used on shape, otherwise the effect will be weird. - // TODOTODO - // shape: elOption.label.shape, - x: elOption.label.x, - y: elOption.label.y - }); - updateLabelShowHide(labelEl, axisPointerModel); - } - }; - /** - * @private - */ - - - BaseAxisPointer.prototype._renderHandle = function (value) { - if (this._dragging || !this.updateHandleTransform) { - return; - } - - var axisPointerModel = this._axisPointerModel; - - var zr = this._api.getZr(); - - var handle = this._handle; - var handleModel = axisPointerModel.getModel('handle'); - var status = axisPointerModel.get('status'); - - if (!handleModel.get('show') || !status || status === 'hide') { - handle && zr.remove(handle); - this._handle = null; - return; - } - - var isInit; - - if (!this._handle) { - isInit = true; - handle = this._handle = createIcon(handleModel.get('icon'), { - cursor: 'move', - draggable: true, - onmousemove: function (e) { - // For mobile device, prevent screen slider on the button. - stop(e.event); - }, - onmousedown: bind(this._onHandleDragMove, this, 0, 0), - drift: bind(this._onHandleDragMove, this), - ondragend: bind(this._onHandleDragEnd, this) - }); - zr.add(handle); - } - - updateMandatoryProps(handle, axisPointerModel, false); // update style - - handle.setStyle(handleModel.getItemStyle(null, ['color', 'borderColor', 'borderWidth', 'opacity', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'])); // update position - - var handleSize = handleModel.get('size'); - - if (!isArray(handleSize)) { - handleSize = [handleSize, handleSize]; - } - - handle.scaleX = handleSize[0] / 2; - handle.scaleY = handleSize[1] / 2; - createOrUpdate(this, '_doDispatchAxisPointer', handleModel.get('throttle') || 0, 'fixRate'); - - this._moveHandleToValue(value, isInit); - }; - - BaseAxisPointer.prototype._moveHandleToValue = function (value, isInit) { - updateProps(this._axisPointerModel, !isInit && this._moveAnimation, this._handle, getHandleTransProps(this.getHandleTransform(value, this._axisModel, this._axisPointerModel))); - }; - - BaseAxisPointer.prototype._onHandleDragMove = function (dx, dy) { - var handle = this._handle; - - if (!handle) { - return; - } - - this._dragging = true; // Persistent for throttle. - - var trans = this.updateHandleTransform(getHandleTransProps(handle), [dx, dy], this._axisModel, this._axisPointerModel); - this._payloadInfo = trans; - handle.stopAnimation(); - handle.attr(getHandleTransProps(trans)); - inner$2(handle).lastProp = null; - - this._doDispatchAxisPointer(); - }; - /** - * Throttled method. - */ - - - BaseAxisPointer.prototype._doDispatchAxisPointer = function () { - var handle = this._handle; - - if (!handle) { - return; - } - - var payloadInfo = this._payloadInfo; - var axisModel = this._axisModel; - - this._api.dispatchAction({ - type: 'updateAxisPointer', - x: payloadInfo.cursorPoint[0], - y: payloadInfo.cursorPoint[1], - tooltipOption: payloadInfo.tooltipOption, - axesInfo: [{ - axisDim: axisModel.axis.dim, - axisIndex: axisModel.componentIndex - }] - }); - }; - - BaseAxisPointer.prototype._onHandleDragEnd = function () { - this._dragging = false; - var handle = this._handle; - - if (!handle) { - return; - } - - var value = this._axisPointerModel.get('value'); // Consider snap or categroy axis, handle may be not consistent with - // axisPointer. So move handle to align the exact value position when - // drag ended. - - - this._moveHandleToValue(value); // For the effect: tooltip will be shown when finger holding on handle - // button, and will be hidden after finger left handle button. - - - this._api.dispatchAction({ - type: 'hideTip' - }); - }; - /** - * @private - */ - - - BaseAxisPointer.prototype.clear = function (api) { - this._lastValue = null; - this._lastStatus = null; - var zr = api.getZr(); - var group = this._group; - var handle = this._handle; - - if (zr && group) { - this._lastGraphicKey = null; - group && zr.remove(group); - handle && zr.remove(handle); - this._group = null; - this._handle = null; - this._payloadInfo = null; - } - - clear(this, '_doDispatchAxisPointer'); - }; - /** - * @protected - */ - - - BaseAxisPointer.prototype.doClear = function () {// Implemented by sub-class if necessary. - }; - - BaseAxisPointer.prototype.buildLabel = function (xy, wh, xDimIndex) { - xDimIndex = xDimIndex || 0; - return { - x: xy[xDimIndex], - y: xy[1 - xDimIndex], - width: wh[xDimIndex], - height: wh[1 - xDimIndex] - }; - }; - - return BaseAxisPointer; - }(); - - function updateProps(animationModel, moveAnimation, el, props) { - // Animation optimize. - if (!propsEqual(inner$2(el).lastProp, props)) { - inner$2(el).lastProp = props; - moveAnimation ? updateProps$1(el, props, animationModel) : (el.stopAnimation(), el.attr(props)); - } - } - - function propsEqual(lastProps, newProps) { - if (isObject$2(lastProps) && isObject$2(newProps)) { - var equals_1 = true; - each$4(newProps, function (item, key) { - equals_1 = equals_1 && propsEqual(lastProps[key], item); - }); - return !!equals_1; - } else { - return lastProps === newProps; - } - } - - function updateLabelShowHide(labelEl, axisPointerModel) { - labelEl[axisPointerModel.get(['label', 'show']) ? 'show' : 'hide'](); - } - - function getHandleTransProps(trans) { - return { - x: trans.x || 0, - y: trans.y || 0, - rotation: trans.rotation || 0 - }; - } - - function updateMandatoryProps(group, axisPointerModel, silent) { - var z = axisPointerModel.get('z'); - var zlevel = axisPointerModel.get('zlevel'); - group && group.traverse(function (el) { - if (el.type !== 'group') { - z != null && (el.z = z); - zlevel != null && (el.zlevel = zlevel); - el.silent = silent; - } - }); - } - - function buildElStyle(axisPointerModel) { - var axisPointerType = axisPointerModel.get('type'); - var styleModel = axisPointerModel.getModel(axisPointerType + 'Style'); - var style; - - if (axisPointerType === 'line') { - style = styleModel.getLineStyle(); - style.fill = null; - } else if (axisPointerType === 'shadow') { - style = styleModel.getAreaStyle(); - style.stroke = null; - } - - return style; - } - /** - * @param {Function} labelPos {align, verticalAlign, position} - */ - - - function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) { - var value = axisPointerModel.get('value'); - var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), { - precision: axisPointerModel.get(['label', 'precision']), - formatter: axisPointerModel.get(['label', 'formatter']) - }); - var labelModel = axisPointerModel.getModel('label'); - var paddings = normalizeCssArray(labelModel.get('padding') || 0); - var font = labelModel.getFont(); - var textRect = getBoundingRect(text, font); - var position = labelPos.position; - var width = textRect.width + paddings[1] + paddings[3]; - var height = textRect.height + paddings[0] + paddings[2]; // Adjust by align. - - var align = labelPos.align; - align === 'right' && (position[0] -= width); - align === 'center' && (position[0] -= width / 2); - var verticalAlign = labelPos.verticalAlign; - verticalAlign === 'bottom' && (position[1] -= height); - verticalAlign === 'middle' && (position[1] -= height / 2); // Not overflow ec container - - confineInContainer(position, width, height, api); - var bgColor = labelModel.get('backgroundColor'); - - if (!bgColor || bgColor === 'auto') { - bgColor = axisModel.get(['axisLine', 'lineStyle', 'color']); - } - - elOption.label = { - // shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')}, - x: position[0], - y: position[1], - style: createTextStyle$1(labelModel, { - text: text, - font: font, - fill: labelModel.getTextColor(), - padding: paddings, - backgroundColor: bgColor - }), - // Label should be over axisPointer. - z2: 10 - }; - } // Do not overflow ec container - - - function confineInContainer(position, width, height, api) { - var viewWidth = api.getWidth(); - var viewHeight = api.getHeight(); - position[0] = Math.min(position[0] + width, viewWidth) - width; - position[1] = Math.min(position[1] + height, viewHeight) - height; - position[0] = Math.max(position[0], 0); - position[1] = Math.max(position[1], 0); - } - - function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) { - value = axis.scale.parse(value); - var text = axis.scale.getLabel({ - value: value - }, { - // If `precision` is set, width can be fixed (like '12.00500'), which - // helps to debounce when when moving label. - precision: opt.precision - }); - var formatter = opt.formatter; - - if (formatter) { - var params_1 = { - value: getAxisRawValue(axis, { - value: value - }), - axisDimension: axis.dim, - axisIndex: axis.index, - seriesData: [] - }; - each$4(seriesDataIndices, function (idxItem) { - var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); - var dataIndex = idxItem.dataIndexInside; - var dataParams = series && series.getDataParams(dataIndex); - dataParams && params_1.seriesData.push(dataParams); - }); - - if (isString(formatter)) { - text = formatter.replace('{value}', text); - } else if (isFunction(formatter)) { - text = formatter(params_1); - } - } - - return text; - } - - function getTransformedPosition(axis, value, layoutInfo) { - var transform = create(); - rotate(transform, transform, layoutInfo.rotation); - translate(transform, transform, layoutInfo.position); - return applyTransform([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform); - } - - function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) { - // @ts-ignore - var textLayout = AxisBuilder.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection); - layoutInfo.labelMargin = axisPointerModel.get(['label', 'margin']); - buildLabelElOption(elOption, axisModel, axisPointerModel, api, { - position: getTransformedPosition(axisModel.axis, value, layoutInfo), - align: textLayout.textAlign, - verticalAlign: textLayout.textVerticalAlign - }); - } - - function makeLineShape(p1, p2, xDimIndex) { - xDimIndex = xDimIndex || 0; - return { - x1: p1[xDimIndex], - y1: p1[1 - xDimIndex], - x2: p2[xDimIndex], - y2: p2[1 - xDimIndex] - }; - } - - function makeRectShape(xy, wh, xDimIndex) { - xDimIndex = xDimIndex || 0; - return { - x: xy[xDimIndex], - y: xy[1 - xDimIndex], - width: wh[xDimIndex], - height: wh[1 - xDimIndex] - }; - } - - var CartesianAxisPointer = - /** @class */ - function (_super) { - __extends(CartesianAxisPointer, _super); - - function CartesianAxisPointer() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - * @override - */ - - - CartesianAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { - var axis = axisModel.axis; - var grid = axis.grid; - var axisPointerType = axisPointerModel.get('type'); - var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); - var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true)); - - if (axisPointerType && axisPointerType !== 'none') { - var elStyle = buildElStyle(axisPointerModel); - var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent); - pointerOption.style = elStyle; - elOption.graphicKey = pointerOption.type; - elOption.pointer = pointerOption; - } - - var layoutInfo = layout(grid.model, axisModel); - buildCartesianSingleLabelElOption( // @ts-ignore - value, elOption, layoutInfo, axisModel, axisPointerModel, api); - }; - /** - * @override - */ - - - CartesianAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) { - var layoutInfo = layout(axisModel.axis.grid.model, axisModel, { - labelInside: false - }); // @ts-ignore - - layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']); - var pos = getTransformedPosition(axisModel.axis, value, layoutInfo); - return { - x: pos[0], - y: pos[1], - rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) - }; - }; - /** - * @override - */ - - - CartesianAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) { - var axis = axisModel.axis; - var grid = axis.grid; - var axisExtent = axis.getGlobalExtent(true); - var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); - var dimIndex = axis.dim === 'x' ? 0 : 1; - var currPosition = [transform.x, transform.y]; - currPosition[dimIndex] += delta[dimIndex]; - currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); - currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); - var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; - var cursorPoint = [cursorOtherValue, cursorOtherValue]; - cursorPoint[dimIndex] = currPosition[dimIndex]; // Make tooltip do not overlap axisPointer and in the middle of the grid. - - var tooltipOptions = [{ - verticalAlign: 'middle' - }, { - align: 'center' - }]; - return { - x: currPosition[0], - y: currPosition[1], - rotation: transform.rotation, - cursorPoint: cursorPoint, - tooltipOption: tooltipOptions[dimIndex] - }; - }; - - return CartesianAxisPointer; - }(BaseAxisPointer); - - function getCartesian(grid, axis) { - var opt = {}; - opt[axis.dim + 'AxisIndex'] = axis.index; - return grid.getCartesian(opt); - } - - var pointerShapeBuilder = { - line: function (axis, pixelValue, otherExtent) { - var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis)); - return { - type: 'Line', - subPixelOptimize: true, - shape: targetShape - }; - }, - shadow: function (axis, pixelValue, otherExtent) { - var bandWidth = Math.max(1, axis.getBandWidth()); - var span = otherExtent[1] - otherExtent[0]; - return { - type: 'Rect', - shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getAxisDimIndex(axis)) - }; - } - }; - - function getAxisDimIndex(axis) { - return axis.dim === 'x' ? 0 : 1; - } - - var AxisPointerModel = - /** @class */ - function (_super) { - __extends(AxisPointerModel, _super); - - function AxisPointerModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = AxisPointerModel.type; - return _this; - } - - AxisPointerModel.type = 'axisPointer'; - AxisPointerModel.defaultOption = { - // 'auto' means that show when triggered by tooltip or handle. - show: 'auto', - // zlevel: 0, - z: 50, - type: 'line', - // axispointer triggered by tootip determine snap automatically, - // see `modelHelper`. - snap: false, - triggerTooltip: true, - triggerEmphasis: true, - value: null, - status: null, - link: [], - // Do not set 'auto' here, otherwise global animation: false - // will not effect at this axispointer. - animation: null, - animationDurationUpdate: 200, - lineStyle: { - color: '#B9BEC9', - width: 1, - type: 'dashed' - }, - shadowStyle: { - color: 'rgba(210,219,238,0.2)' - }, - label: { - show: true, - formatter: null, - precision: 'auto', - margin: 3, - color: '#fff', - padding: [5, 7, 5, 7], - backgroundColor: 'auto', - borderColor: null, - borderWidth: 0, - borderRadius: 3 - }, - handle: { - show: false, - // eslint-disable-next-line - icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', - size: 45, - // handle margin is from symbol center to axis, which is stable when circular move. - margin: 50, - // color: '#1b8bbd' - // color: '#2f4554' - color: '#333', - shadowBlur: 3, - shadowColor: '#aaa', - shadowOffsetX: 0, - shadowOffsetY: 2, - // For mobile performance - throttle: 40 - } - }; - return AxisPointerModel; - }(ComponentModel); - - var inner$1 = makeInner(); - var each = each$4; - /** - * @param {string} key - * @param {module:echarts/ExtensionAPI} api - * @param {Function} handler - * param: {string} currTrigger - * param: {Array.} point - */ - - function register(key, api, handler) { - if (env.node) { - return; - } - - var zr = api.getZr(); - inner$1(zr).records || (inner$1(zr).records = {}); - initGlobalListeners(zr, api); - var record = inner$1(zr).records[key] || (inner$1(zr).records[key] = {}); - record.handler = handler; - } - - function initGlobalListeners(zr, api) { - if (inner$1(zr).initialized) { - return; - } - - inner$1(zr).initialized = true; - useHandler('click', curry$1(doEnter, 'click')); - useHandler('mousemove', curry$1(doEnter, 'mousemove')); // useHandler('mouseout', onLeave); - - useHandler('globalout', onLeave); - - function useHandler(eventType, cb) { - zr.on(eventType, function (e) { - var dis = makeDispatchAction$1(api); - each(inner$1(zr).records, function (record) { - record && cb(record, e, dis.dispatchAction); - }); - dispatchTooltipFinally(dis.pendings, api); - }); - } - } - - function dispatchTooltipFinally(pendings, api) { - var showLen = pendings.showTip.length; - var hideLen = pendings.hideTip.length; - var actuallyPayload; - - if (showLen) { - actuallyPayload = pendings.showTip[showLen - 1]; - } else if (hideLen) { - actuallyPayload = pendings.hideTip[hideLen - 1]; - } - - if (actuallyPayload) { - actuallyPayload.dispatchAction = null; - api.dispatchAction(actuallyPayload); - } - } - - function onLeave(record, e, dispatchAction) { - record.handler('leave', null, dispatchAction); - } - - function doEnter(currTrigger, record, e, dispatchAction) { - record.handler(currTrigger, e, dispatchAction); - } - - function makeDispatchAction$1(api) { - var pendings = { - showTip: [], - hideTip: [] - }; // FIXME - // better approach? - // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip, - // which may be conflict, (axisPointer call showTip but tooltip call hideTip); - // So we have to add "final stage" to merge those dispatched actions. - - var dispatchAction = function (payload) { - var pendingList = pendings[payload.type]; - - if (pendingList) { - pendingList.push(payload); - } else { - payload.dispatchAction = dispatchAction; - api.dispatchAction(payload); - } - }; - - return { - dispatchAction: dispatchAction, - pendings: pendings - }; - } - - function unregister(key, api) { - if (env.node) { - return; - } - - var zr = api.getZr(); - var record = (inner$1(zr).records || {})[key]; - - if (record) { - inner$1(zr).records[key] = null; - } - } - - var AxisPointerView = - /** @class */ - function (_super) { - __extends(AxisPointerView, _super); - - function AxisPointerView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = AxisPointerView.type; - return _this; - } - - AxisPointerView.prototype.render = function (globalAxisPointerModel, ecModel, api) { - var globalTooltipModel = ecModel.getComponent('tooltip'); - var triggerOn = globalAxisPointerModel.get('triggerOn') || globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'; // Register global listener in AxisPointerView to enable - // AxisPointerView to be independent to Tooltip. - - register('axisPointer', api, function (currTrigger, e, dispatchAction) { - // If 'none', it is not controlled by mouse totally. - if (triggerOn !== 'none' && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)) { - dispatchAction({ - type: 'updateAxisPointer', - currTrigger: currTrigger, - x: e && e.offsetX, - y: e && e.offsetY - }); - } - }); - }; - - AxisPointerView.prototype.remove = function (ecModel, api) { - unregister('axisPointer', api); - }; - - AxisPointerView.prototype.dispose = function (ecModel, api) { - unregister('axisPointer', api); - }; - - AxisPointerView.type = 'axisPointer'; - return AxisPointerView; - }(ComponentView); - /** - * @param finder contains {seriesIndex, dataIndex, dataIndexInside} - * @param ecModel - * @return {point: [x, y], el: ...} point Will not be null. - */ - - - function findPointFromSeries(finder, ecModel) { - var point = []; - var seriesIndex = finder.seriesIndex; - var seriesModel; - - if (seriesIndex == null || !(seriesModel = ecModel.getSeriesByIndex(seriesIndex))) { - return { - point: [] - }; - } - - var data = seriesModel.getData(); - var dataIndex = queryDataIndex(data, finder); - - if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) { - return { - point: [] - }; - } - - var el = data.getItemGraphicEl(dataIndex); - var coordSys = seriesModel.coordinateSystem; - - if (seriesModel.getTooltipPosition) { - point = seriesModel.getTooltipPosition(dataIndex) || []; - } else if (coordSys && coordSys.dataToPoint) { - if (finder.isStacked) { - var baseAxis = coordSys.getBaseAxis(); - var valueAxis = coordSys.getOtherAxis(baseAxis); - var valueAxisDim = valueAxis.dim; - var baseAxisDim = baseAxis.dim; - var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; - var baseDim = data.mapDimension(baseAxisDim); - var stackedData = []; - stackedData[baseDataOffset] = data.get(baseDim, dataIndex); - stackedData[1 - baseDataOffset] = data.get(data.getCalculationInfo('stackResultDimension'), dataIndex); - point = coordSys.dataToPoint(stackedData) || []; - } else { - point = coordSys.dataToPoint(data.getValues(map$1(coordSys.dimensions, function (dim) { - return data.mapDimension(dim); - }), dataIndex)) || []; - } - } else if (el) { - // Use graphic bounding rect - var rect = el.getBoundingRect().clone(); - rect.applyTransform(el.transform); - point = [rect.x + rect.width / 2, rect.y + rect.height / 2]; - } - - return { - point: point, - el: el - }; - } - - var inner = makeInner(); - /** - * Basic logic: check all axis, if they do not demand show/highlight, - * then hide/downplay them. - * - * @return content of event obj for echarts.connect. - */ - - function axisTrigger(payload, ecModel, api) { - var currTrigger = payload.currTrigger; - var point = [payload.x, payload.y]; - var finder = payload; - var dispatchAction = payload.dispatchAction || bind$1(api.dispatchAction, api); - var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; // Pending - // See #6121. But we are not able to reproduce it yet. - - if (!coordSysAxesInfo) { - return; - } - - if (illegalPoint(point)) { - // Used in the default behavior of `connection`: use the sample seriesIndex - // and dataIndex. And also used in the tooltipView trigger. - point = findPointFromSeries({ - seriesIndex: finder.seriesIndex, - // Do not use dataIndexInside from other ec instance. - // FIXME: auto detect it? - dataIndex: finder.dataIndex - }, ecModel).point; - } - - var isIllegalPoint = illegalPoint(point); // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}). - // Notice: In this case, it is difficult to get the `point` (which is necessary to show - // tooltip, so if point is not given, we just use the point found by sample seriesIndex - // and dataIndex. - - var inputAxesInfo = finder.axesInfo; - var axesInfo = coordSysAxesInfo.axesInfo; - var shouldHide = currTrigger === 'leave' || illegalPoint(point); - var outputPayload = {}; - var showValueMap = {}; - var dataByCoordSys = { - list: [], - map: {} - }; - var updaters = { - showPointer: curry$1(showPointer, showValueMap), - showTooltip: curry$1(showTooltip, dataByCoordSys) - }; // Process for triggered axes. - - each$4(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) { - // If a point given, it must be contained by the coordinate system. - var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point); - each$4(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) { - var axis = axisInfo.axis; - var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); // If no inputAxesInfo, no axis is restricted. - - if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) { - var val = inputAxisInfo && inputAxisInfo.value; - - if (val == null && !isIllegalPoint) { - val = axis.pointToData(point); - } - - val != null && processOnAxis(axisInfo, val, updaters, false, outputPayload); - } - }); - }); // Process for linked axes. - - var linkTriggers = {}; - each$4(axesInfo, function (tarAxisInfo, tarKey) { - var linkGroup = tarAxisInfo.linkGroup; // If axis has been triggered in the previous stage, it should not be triggered by link. - - if (linkGroup && !showValueMap[tarKey]) { - each$4(linkGroup.axesInfo, function (srcAxisInfo, srcKey) { - var srcValItem = showValueMap[srcKey]; // If srcValItem exist, source axis is triggered, so link to target axis. - - if (srcAxisInfo !== tarAxisInfo && srcValItem) { - var val = srcValItem.value; - linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo)))); - linkTriggers[tarAxisInfo.key] = val; - } - }); - } - }); - each$4(linkTriggers, function (val, tarKey) { - processOnAxis(axesInfo[tarKey], val, updaters, true, outputPayload); - }); - updateModelActually(showValueMap, axesInfo, outputPayload); - dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction); - dispatchHighDownActually(axesInfo, dispatchAction, api); - return outputPayload; - } - - function processOnAxis(axisInfo, newValue, updaters, noSnap, outputFinder) { - var axis = axisInfo.axis; - - if (axis.scale.isBlank() || !axis.containData(newValue)) { - return; - } - - if (!axisInfo.involveSeries) { - updaters.showPointer(axisInfo, newValue); - return; - } // Heavy calculation. So put it after axis.containData checking. - - - var payloadInfo = buildPayloadsBySeries(newValue, axisInfo); - var payloadBatch = payloadInfo.payloadBatch; - var snapToValue = payloadInfo.snapToValue; // Fill content of event obj for echarts.connect. - // By default use the first involved series data as a sample to connect. - - if (payloadBatch[0] && outputFinder.seriesIndex == null) { - extend(outputFinder, payloadBatch[0]); - } // If no linkSource input, this process is for collecting link - // target, where snap should not be accepted. - - - if (!noSnap && axisInfo.snap) { - if (axis.containData(snapToValue) && snapToValue != null) { - newValue = snapToValue; - } - } - - updaters.showPointer(axisInfo, newValue, payloadBatch); // Tooltip should always be snapToValue, otherwise there will be - // incorrect "axis value ~ series value" mapping displayed in tooltip. - - updaters.showTooltip(axisInfo, payloadInfo, snapToValue); - } - - function buildPayloadsBySeries(value, axisInfo) { - var axis = axisInfo.axis; - var dim = axis.dim; - var snapToValue = value; - var payloadBatch = []; - var minDist = Number.MAX_VALUE; - var minDiff = -1; - each$4(axisInfo.seriesModels, function (series, idx) { - var dataDim = series.getData().mapDimensionsAll(dim); - var seriesNestestValue; - var dataIndices; - - if (series.getAxisTooltipData) { - var result = series.getAxisTooltipData(dataDim, value, axis); - dataIndices = result.dataIndices; - seriesNestestValue = result.nestestValue; - } else { - dataIndices = series.getData().indicesOfNearest(dataDim[0], value, // Add a threshold to avoid find the wrong dataIndex - // when data length is not same. - // false, - axis.type === 'category' ? 0.5 : null); - - if (!dataIndices.length) { - return; - } - - seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]); - } - - if (seriesNestestValue == null || !isFinite(seriesNestestValue)) { - return; - } - - var diff = value - seriesNestestValue; - var dist = Math.abs(diff); // Consider category case - - if (dist <= minDist) { - if (dist < minDist || diff >= 0 && minDiff < 0) { - minDist = dist; - minDiff = diff; - snapToValue = seriesNestestValue; - payloadBatch.length = 0; - } - - each$4(dataIndices, function (dataIndex) { - payloadBatch.push({ - seriesIndex: series.seriesIndex, - dataIndexInside: dataIndex, - dataIndex: series.getData().getRawIndex(dataIndex) - }); - }); - } - }); - return { - payloadBatch: payloadBatch, - snapToValue: snapToValue - }; - } - - function showPointer(showValueMap, axisInfo, value, payloadBatch) { - showValueMap[axisInfo.key] = { - value: value, - payloadBatch: payloadBatch - }; - } - - function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) { - var payloadBatch = payloadInfo.payloadBatch; - var axis = axisInfo.axis; - var axisModel = axis.model; - var axisPointerModel = axisInfo.axisPointerModel; // If no data, do not create anything in dataByCoordSys, - // whose length will be used to judge whether dispatch action. - - if (!axisInfo.triggerTooltip || !payloadBatch.length) { - return; - } - - var coordSysModel = axisInfo.coordSys.model; - var coordSysKey = makeKey(coordSysModel); - var coordSysItem = dataByCoordSys.map[coordSysKey]; - - if (!coordSysItem) { - coordSysItem = dataByCoordSys.map[coordSysKey] = { - coordSysId: coordSysModel.id, - coordSysIndex: coordSysModel.componentIndex, - coordSysType: coordSysModel.type, - coordSysMainType: coordSysModel.mainType, - dataByAxis: [] - }; - dataByCoordSys.list.push(coordSysItem); - } - - coordSysItem.dataByAxis.push({ - axisDim: axis.dim, - axisIndex: axisModel.componentIndex, - axisType: axisModel.type, - axisId: axisModel.id, - value: value, - // Caustion: viewHelper.getValueLabel is actually on "view stage", which - // depends that all models have been updated. So it should not be performed - // here. Considering axisPointerModel used here is volatile, which is hard - // to be retrieve in TooltipView, we prepare parameters here. - valueLabelOpt: { - precision: axisPointerModel.get(['label', 'precision']), - formatter: axisPointerModel.get(['label', 'formatter']) - }, - seriesDataIndices: payloadBatch.slice() - }); - } - - function updateModelActually(showValueMap, axesInfo, outputPayload) { - var outputAxesInfo = outputPayload.axesInfo = []; // Basic logic: If no 'show' required, 'hide' this axisPointer. - - each$4(axesInfo, function (axisInfo, key) { - var option = axisInfo.axisPointerModel.option; - var valItem = showValueMap[key]; - - if (valItem) { - !axisInfo.useHandle && (option.status = 'show'); - option.value = valItem.value; // For label formatter param and highlight. - - option.seriesDataIndices = (valItem.payloadBatch || []).slice(); - } // When always show (e.g., handle used), remain - // original value and status. - else { - // If hide, value still need to be set, consider - // click legend to toggle axis blank. - !axisInfo.useHandle && (option.status = 'hide'); - } // If status is 'hide', should be no info in payload. - - - option.status === 'show' && outputAxesInfo.push({ - axisDim: axisInfo.axis.dim, - axisIndex: axisInfo.axis.model.componentIndex, - value: option.value - }); - }); - } - - function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) { - // Basic logic: If no showTip required, hideTip will be dispatched. - if (illegalPoint(point) || !dataByCoordSys.list.length) { - dispatchAction({ - type: 'hideTip' - }); - return; - } // In most case only one axis (or event one series is used). It is - // convenient to fetch payload.seriesIndex and payload.dataIndex - // directly. So put the first seriesIndex and dataIndex of the first - // axis on the payload. - - - var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {}; - dispatchAction({ - type: 'showTip', - escapeConnect: true, - x: point[0], - y: point[1], - tooltipOption: payload.tooltipOption, - position: payload.position, - dataIndexInside: sampleItem.dataIndexInside, - dataIndex: sampleItem.dataIndex, - seriesIndex: sampleItem.seriesIndex, - dataByCoordSys: dataByCoordSys.list - }); - } - - function dispatchHighDownActually(axesInfo, dispatchAction, api) { - // FIXME - // highlight status modification should be a stage of main process? - // (Consider confilct (e.g., legend and axisPointer) and setOption) - var zr = api.getZr(); - var highDownKey = 'axisPointerLastHighlights'; - var lastHighlights = inner(zr)[highDownKey] || {}; - var newHighlights = inner(zr)[highDownKey] = {}; // Update highlight/downplay status according to axisPointer model. - // Build hash map and remove duplicate incidentally. - - each$4(axesInfo, function (axisInfo, key) { - var option = axisInfo.axisPointerModel.option; - option.status === 'show' && axisInfo.triggerEmphasis && each$4(option.seriesDataIndices, function (batchItem) { - var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex; - newHighlights[key] = batchItem; - }); - }); // Diff. - - var toHighlight = []; - var toDownplay = []; - each$4(lastHighlights, function (batchItem, key) { - !newHighlights[key] && toDownplay.push(batchItem); - }); - each$4(newHighlights, function (batchItem, key) { - !lastHighlights[key] && toHighlight.push(batchItem); - }); - toDownplay.length && api.dispatchAction({ - type: 'downplay', - escapeConnect: true, - // Not blur others when highlight in axisPointer. - notBlur: true, - batch: toDownplay - }); - toHighlight.length && api.dispatchAction({ - type: 'highlight', - escapeConnect: true, - // Not blur others when highlight in axisPointer. - notBlur: true, - batch: toHighlight - }); - } - - function findInputAxisInfo(inputAxesInfo, axisInfo) { - for (var i = 0; i < (inputAxesInfo || []).length; i++) { - var inputAxisInfo = inputAxesInfo[i]; - - if (axisInfo.axis.dim === inputAxisInfo.axisDim && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex) { - return inputAxisInfo; - } - } - } - - function makeMapperParam(axisInfo) { - var axisModel = axisInfo.axis.model; - var item = {}; - var dim = item.axisDim = axisInfo.axis.dim; - item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex; - item.axisName = item[dim + 'AxisName'] = axisModel.name; - item.axisId = item[dim + 'AxisId'] = axisModel.id; - return item; - } - - function illegalPoint(point) { - return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]); - } - - function install$2(registers) { - // CartesianAxisPointer is not supposed to be required here. But consider - // echarts.simple.js and online build tooltip, which only require gridSimple, - // CartesianAxisPointer should be able to required somewhere. - AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer); - registers.registerComponentModel(AxisPointerModel); - registers.registerComponentView(AxisPointerView); - registers.registerPreprocessor(function (option) { - // Always has a global axisPointerModel for default setting. - if (option) { - (!option.axisPointer || option.axisPointer.length === 0) && (option.axisPointer = {}); - var link = option.axisPointer.link; // Normalize to array to avoid object mergin. But if link - // is not set, remain null/undefined, otherwise it will - // override existent link setting. - - if (link && !isArray(link)) { - option.axisPointer.link = [link]; - } - } - }); // This process should proformed after coordinate systems created - // and series data processed. So put it on statistic processing stage. - - registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) { - // Build axisPointerModel, mergin tooltip.axisPointer model for each axis. - // allAxesInfo should be updated when setOption performed. - ecModel.getComponent('axisPointer').coordSysAxesInfo = collect(ecModel, api); - }); // Broadcast to all views. - - registers.registerAction({ - type: 'updateAxisPointer', - event: 'updateAxisPointer', - update: ':updateAxisPointer' - }, axisTrigger); - } - - var TooltipModel = - /** @class */ - function (_super) { - __extends(TooltipModel, _super); - - function TooltipModel() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = TooltipModel.type; - return _this; - } - - TooltipModel.type = 'tooltip'; - TooltipModel.dependencies = ['axisPointer']; - TooltipModel.defaultOption = { - // zlevel: 0, - z: 60, - show: true, - // tooltip main content - showContent: true, - // 'trigger' only works on coordinate system. - // 'item' | 'axis' | 'none' - trigger: 'item', - // 'click' | 'mousemove' | 'none' - triggerOn: 'mousemove|click', - alwaysShowContent: false, - displayMode: 'single', - renderMode: 'auto', - // whether restraint content inside viewRect. - // If renderMode: 'richText', default true. - // If renderMode: 'html', defaut false (for backward compat). - confine: null, - showDelay: 0, - hideDelay: 100, - // Animation transition time, unit is second - transitionDuration: 0.4, - enterable: false, - backgroundColor: '#fff', - // box shadow - shadowBlur: 10, - shadowColor: 'rgba(0, 0, 0, .2)', - shadowOffsetX: 1, - shadowOffsetY: 2, - // tooltip border radius, unit is px, default is 4 - borderRadius: 4, - // tooltip border width, unit is px, default is 0 (no border) - borderWidth: 1, - // Tooltip inside padding, default is 5 for all direction - // Array is allowed to set up, right, bottom, left, same with css - // The default value: See `tooltip/tooltipMarkup.ts#getPaddingFromTooltipModel`. - padding: null, - // Extra css text - extraCssText: '', - // axis indicator, trigger by axis - axisPointer: { - // default is line - // legal values: 'line' | 'shadow' | 'cross' - type: 'line', - // Valid when type is line, appoint tooltip line locate on which line. Optional - // legal values: 'x' | 'y' | 'angle' | 'radius' | 'auto' - // default is 'auto', chose the axis which type is category. - // for multiply y axis, cartesian coord chose x axis, polar chose angle axis - axis: 'auto', - animation: 'auto', - animationDurationUpdate: 200, - animationEasingUpdate: 'exponentialOut', - crossStyle: { - color: '#999', - width: 1, - type: 'dashed', - // TODO formatter - textStyle: {} - } // lineStyle and shadowStyle should not be specified here, - // otherwise it will always override those styles on option.axisPointer. - - }, - textStyle: { - color: '#666', - fontSize: 14 - } - }; - return TooltipModel; - }(ComponentModel); - /* global document */ - - - function shouldTooltipConfine(tooltipModel) { - var confineOption = tooltipModel.get('confine'); - return confineOption != null ? !!confineOption // In richText mode, the outside part can not be visible. - : tooltipModel.get('renderMode') === 'richText'; - } - - function testStyle(styleProps) { - if (!env.domSupported) { - return; - } - - var style = document.documentElement.style; - - for (var i = 0, len = styleProps.length; i < len; i++) { - if (styleProps[i] in style) { - return styleProps[i]; - } - } - } - - var TRANSFORM_VENDOR = testStyle(['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); - var TRANSITION_VENDOR = testStyle(['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); - - function toCSSVendorPrefix(styleVendor, styleProp) { - if (!styleVendor) { - return styleProp; - } - - styleProp = toCamelCase(styleProp, true); - var idx = styleVendor.indexOf(styleProp); - styleVendor = idx === -1 ? styleProp : "-" + styleVendor.slice(0, idx) + "-" + styleProp; - return styleVendor.toLowerCase(); - } - - function getComputedStyle(el, style) { - var stl = el.currentStyle || document.defaultView && document.defaultView.getComputedStyle(el); - return stl ? style ? stl[style] : stl : null; - } - /* global document, window */ - - - var CSS_TRANSITION_VENDOR = toCSSVendorPrefix(TRANSITION_VENDOR, 'transition'); - var CSS_TRANSFORM_VENDOR = toCSSVendorPrefix(TRANSFORM_VENDOR, 'transform'); // eslint-disable-next-line - - var gCssText = "position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;" + (env.transform3dSupported ? 'will-change:transform;' : ''); - - function mirrorPos(pos) { - pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top'; - return pos; - } - - function assembleArrow(tooltipModel, borderColor, arrowPosition) { - if (!isString(arrowPosition) || arrowPosition === 'inside') { - return ''; - } - - var backgroundColor = tooltipModel.get('backgroundColor'); - var borderWidth = tooltipModel.get('borderWidth'); - borderColor = convertToColorString(borderColor); - var arrowPos = mirrorPos(arrowPosition); - var arrowSize = Math.max(Math.round(borderWidth) * 1.5, 6); - var positionStyle = ''; - var transformStyle = CSS_TRANSFORM_VENDOR + ':'; - var rotateDeg; - - if (indexOf(['left', 'right'], arrowPos) > -1) { - positionStyle += 'top:50%'; - transformStyle += "translateY(-50%) rotate(" + (rotateDeg = arrowPos === 'left' ? -225 : -45) + "deg)"; - } else { - positionStyle += 'left:50%'; - transformStyle += "translateX(-50%) rotate(" + (rotateDeg = arrowPos === 'top' ? 225 : 45) + "deg)"; - } - - var rotateRadian = rotateDeg * Math.PI / 180; - var arrowWH = arrowSize + borderWidth; - var rotatedWH = arrowWH * Math.abs(Math.cos(rotateRadian)) + arrowWH * Math.abs(Math.sin(rotateRadian)); - var arrowOffset = Math.round(((rotatedWH - Math.SQRT2 * borderWidth) / 2 + Math.SQRT2 * borderWidth - (rotatedWH - arrowWH) / 2) * 100) / 100; - positionStyle += ";" + arrowPos + ":-" + arrowOffset + "px"; - var borderStyle = borderColor + " solid " + borderWidth + "px;"; - var styleCss = ["position:absolute;width:" + arrowSize + "px;height:" + arrowSize + "px;z-index:-1;", positionStyle + ";" + transformStyle + ";", "border-bottom:" + borderStyle, "border-right:" + borderStyle, "background-color:" + backgroundColor + ";"]; - return "
"; - } - - function assembleTransition(duration, onlyFade) { - var transitionCurve = 'cubic-bezier(0.23,1,0.32,1)'; - var transitionOption = " " + duration / 2 + "s " + transitionCurve; - var transitionText = "opacity" + transitionOption + ",visibility" + transitionOption; - - if (!onlyFade) { - transitionOption = " " + duration + "s " + transitionCurve; - transitionText += env.transformSupported ? "," + CSS_TRANSFORM_VENDOR + transitionOption : ",left" + transitionOption + ",top" + transitionOption; - } - - return CSS_TRANSITION_VENDOR + ':' + transitionText; - } - - function assembleTransform(x, y, toString) { - // If using float on style, the final width of the dom might - // keep changing slightly while mouse move. So `toFixed(0)` them. - var x0 = x.toFixed(0) + 'px'; - var y0 = y.toFixed(0) + 'px'; // not support transform, use `left` and `top` instead. - - if (!env.transformSupported) { - return toString ? "top:" + y0 + ";left:" + x0 + ";" : [['top', y0], ['left', x0]]; - } // support transform - - - var is3d = env.transform3dSupported; - var translate = "translate" + (is3d ? '3d' : '') + "(" + x0 + "," + y0 + (is3d ? ',0' : '') + ")"; - return toString ? 'top:0;left:0;' + CSS_TRANSFORM_VENDOR + ':' + translate + ';' : [['top', 0], ['left', 0], [TRANSFORM_VENDOR, translate]]; - } - /** - * @param {Object} textStyle - * @return {string} - * @inner - */ - - - function assembleFont(textStyleModel) { - var cssText = []; - var fontSize = textStyleModel.get('fontSize'); - var color = textStyleModel.getTextColor(); - color && cssText.push('color:' + color); - cssText.push('font:' + textStyleModel.getFont()); - fontSize // @ts-ignore, leave it to the tooltip refactor. - && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px'); - var shadowColor = textStyleModel.get('textShadowColor'); - var shadowBlur = textStyleModel.get('textShadowBlur') || 0; - var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0; - var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0; - shadowColor && shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor); - each$4(['decoration', 'align'], function (name) { - var val = textStyleModel.get(name); - val && cssText.push('text-' + name + ':' + val); - }); - return cssText.join(';'); - } - - function assembleCssText(tooltipModel, enableTransition, onlyFade) { - var cssText = []; - var transitionDuration = tooltipModel.get('transitionDuration'); - var backgroundColor = tooltipModel.get('backgroundColor'); - var shadowBlur = tooltipModel.get('shadowBlur'); - var shadowColor = tooltipModel.get('shadowColor'); - var shadowOffsetX = tooltipModel.get('shadowOffsetX'); - var shadowOffsetY = tooltipModel.get('shadowOffsetY'); - var textStyleModel = tooltipModel.getModel('textStyle'); - var padding = getPaddingFromTooltipModel(tooltipModel, 'html'); - var boxShadow = shadowOffsetX + "px " + shadowOffsetY + "px " + shadowBlur + "px " + shadowColor; - cssText.push('box-shadow:' + boxShadow); // Animation transition. Do not animate when transitionDuration is 0. - - enableTransition && transitionDuration && cssText.push(assembleTransition(transitionDuration, onlyFade)); - - if (backgroundColor) { - cssText.push('background-color:' + backgroundColor); - } // Border style - - - each$4(['width', 'color', 'radius'], function (name) { - var borderName = 'border-' + name; - var camelCase = toCamelCase(borderName); - var val = tooltipModel.get(camelCase); - val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px')); - }); // Text style - - cssText.push(assembleFont(textStyleModel)); // Padding - - if (padding != null) { - cssText.push('padding:' + normalizeCssArray(padding).join('px ') + 'px'); - } - - return cssText.join(';') + ';'; - } // If not able to make, do not modify the input `out`. - - - function makeStyleCoord$1(out, zr, container, zrX, zrY) { - var zrPainter = zr && zr.painter; - - if (container) { - var zrViewportRoot = zrPainter && zrPainter.getViewportRoot(); - - if (zrViewportRoot) { - // Some APPs might use scale on body, so we support CSS transform here. - transformLocalCoord(out, zrViewportRoot, container, zrX, zrY); - } - } else { - out[0] = zrX; - out[1] = zrY; // xy should be based on canvas root. But tooltipContent is - // the sibling of canvas root. So padding of ec container - // should be considered here. - - var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset(); - - if (viewportRootOffset) { - out[0] += viewportRootOffset.offsetLeft; - out[1] += viewportRootOffset.offsetTop; - } - } - - out[2] = out[0] / zr.getWidth(); - out[3] = out[1] / zr.getHeight(); - } - - var TooltipHTMLContent = - /** @class */ - function () { - function TooltipHTMLContent(api, opt) { - this._show = false; - this._styleCoord = [0, 0, 0, 0]; - this._enterable = true; - this._alwaysShowContent = false; - this._firstShow = true; - this._longHide = true; - - if (env.wxa) { - return null; - } - - var el = document.createElement('div'); // TODO: TYPE - - el.domBelongToZr = true; - this.el = el; - var zr = this._zr = api.getZr(); - var appendTo = opt.appendTo; - var container = appendTo && (isString(appendTo) ? document.querySelector(appendTo) : isDom(appendTo) ? appendTo : isFunction(appendTo) && appendTo(api.getDom())); - makeStyleCoord$1(this._styleCoord, zr, container, api.getWidth() / 2, api.getHeight() / 2); - (container || api.getDom()).appendChild(el); - this._api = api; - this._container = container; // FIXME - // Is it needed to trigger zr event manually if - // the browser do not support `pointer-events: none`. - - var self = this; - - el.onmouseenter = function () { - // clear the timeout in hideLater and keep showing tooltip - if (self._enterable) { - clearTimeout(self._hideTimeout); - self._show = true; - } - - self._inContent = true; - }; - - el.onmousemove = function (e) { - e = e || window.event; - - if (!self._enterable) { - // `pointer-events: none` is set to tooltip content div - // if `enterable` is set as `false`, and `el.onmousemove` - // can not be triggered. But in browser that do not - // support `pointer-events`, we need to do this: - // Try trigger zrender event to avoid mouse - // in and out shape too frequently - var handler = zr.handler; - var zrViewportRoot = zr.painter.getViewportRoot(); - normalizeEvent(zrViewportRoot, e, true); - handler.dispatch('mousemove', e); - } - }; - - el.onmouseleave = function () { - // set `_inContent` to `false` before `hideLater` - self._inContent = false; - - if (self._enterable) { - if (self._show) { - self.hideLater(self._hideDelay); - } - } - }; - } - /** - * Update when tooltip is rendered - */ - - - TooltipHTMLContent.prototype.update = function (tooltipModel) { - // FIXME - // Move this logic to ec main? - if (!this._container) { - var container = this._api.getDom(); - - var position = getComputedStyle(container, 'position'); - var domStyle = container.style; - - if (domStyle.position !== 'absolute' && position !== 'absolute') { - domStyle.position = 'relative'; - } - } // move tooltip if chart resized - - - var alwaysShowContent = tooltipModel.get('alwaysShowContent'); - alwaysShowContent && this._moveIfResized(); // update alwaysShowContent - - this._alwaysShowContent = alwaysShowContent; // update className - - this.el.className = tooltipModel.get('className') || ''; // Hide the tooltip - // PENDING - // this.hide(); - }; - - TooltipHTMLContent.prototype.show = function (tooltipModel, nearPointColor) { - clearTimeout(this._hideTimeout); - clearTimeout(this._longHideTimeout); - var el = this.el; - var style = el.style; - var styleCoord = this._styleCoord; - - if (!el.innerHTML) { - style.display = 'none'; - } else { - style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) // initial transform - + assembleTransform(styleCoord[0], styleCoord[1], true) + ("border-color:" + convertToColorString(nearPointColor) + ";") + (tooltipModel.get('extraCssText') || '') // If mouse occasionally move over the tooltip, a mouseout event will be - // triggered by canvas, and cause some unexpectable result like dragging - // stop, "unfocusAdjacency". Here `pointer-events: none` is used to solve - // it. Although it is not supported by IE8~IE10, fortunately it is a rare - // scenario. - + (";pointer-events:" + (this._enterable ? 'auto' : 'none')); - } - - this._show = true; - this._firstShow = false; - this._longHide = false; - }; - - TooltipHTMLContent.prototype.setContent = function (content, markers, tooltipModel, borderColor, arrowPosition) { - var el = this.el; - - if (content == null) { - el.innerHTML = ''; - return; - } - - var arrow = ''; - - if (isString(arrowPosition) && tooltipModel.get('trigger') === 'item' && !shouldTooltipConfine(tooltipModel)) { - arrow = assembleArrow(tooltipModel, borderColor, arrowPosition); - } - - if (isString(content)) { - el.innerHTML = content + arrow; - } else if (content) { - // Clear previous - el.innerHTML = ''; - - if (!isArray(content)) { - content = [content]; - } - - for (var i = 0; i < content.length; i++) { - if (isDom(content[i]) && content[i].parentNode !== el) { - el.appendChild(content[i]); - } - } // no arrow if empty - - - if (arrow && el.childNodes.length) { - // no need to create a new parent element, but it's not supported by IE 10 and older. - // const arrowEl = document.createRange().createContextualFragment(arrow); - var arrowEl = document.createElement('div'); - arrowEl.innerHTML = arrow; - el.appendChild(arrowEl); - } - } - }; - - TooltipHTMLContent.prototype.setEnterable = function (enterable) { - this._enterable = enterable; - }; - - TooltipHTMLContent.prototype.getSize = function () { - var el = this.el; - return [el.offsetWidth, el.offsetHeight]; - }; - - TooltipHTMLContent.prototype.moveTo = function (zrX, zrY) { - var styleCoord = this._styleCoord; - makeStyleCoord$1(styleCoord, this._zr, this._container, zrX, zrY); - - if (styleCoord[0] != null && styleCoord[1] != null) { - var style_1 = this.el.style; - var transforms = assembleTransform(styleCoord[0], styleCoord[1]); - each$4(transforms, function (transform) { - style_1[transform[0]] = transform[1]; - }); - } - }; - /** - * when `alwaysShowContent` is true, - * move the tooltip after chart resized - */ - - - TooltipHTMLContent.prototype._moveIfResized = function () { - // The ratio of left to width - var ratioX = this._styleCoord[2]; // The ratio of top to height - - var ratioY = this._styleCoord[3]; - this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); - }; - - TooltipHTMLContent.prototype.hide = function () { - var _this = this; - - var style = this.el.style; - style.visibility = 'hidden'; - style.opacity = '0'; - env.transform3dSupported && (style.willChange = ''); - this._show = false; - this._longHideTimeout = setTimeout(function () { - return _this._longHide = true; - }, 500); - }; - - TooltipHTMLContent.prototype.hideLater = function (time) { - if (this._show && !(this._inContent && this._enterable) && !this._alwaysShowContent) { - if (time) { - this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times - - this._show = false; - this._hideTimeout = setTimeout(bind$1(this.hide, this), time); - } else { - this.hide(); - } - } - }; - - TooltipHTMLContent.prototype.isShow = function () { - return this._show; - }; - - TooltipHTMLContent.prototype.dispose = function () { - clearTimeout(this._hideTimeout); - clearTimeout(this._longHideTimeout); - var parentNode = this.el.parentNode; - parentNode && parentNode.removeChild(this.el); - this.el = this._container = null; - }; - - return TooltipHTMLContent; - }(); - - var TooltipRichContent = - /** @class */ - function () { - function TooltipRichContent(api) { - this._show = false; - this._styleCoord = [0, 0, 0, 0]; - this._alwaysShowContent = false; - this._enterable = true; - this._zr = api.getZr(); - makeStyleCoord(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2); - } - /** - * Update when tooltip is rendered - */ - - - TooltipRichContent.prototype.update = function (tooltipModel) { - var alwaysShowContent = tooltipModel.get('alwaysShowContent'); - alwaysShowContent && this._moveIfResized(); // update alwaysShowContent - - this._alwaysShowContent = alwaysShowContent; - }; - - TooltipRichContent.prototype.show = function () { - if (this._hideTimeout) { - clearTimeout(this._hideTimeout); - } - - this.el.show(); - this._show = true; - }; - /** - * Set tooltip content - */ - - - TooltipRichContent.prototype.setContent = function (content, markupStyleCreator, tooltipModel, borderColor, arrowPosition) { - var _this = this; - - if (isObject$2(content)) { - throwError('Passing DOM nodes as content is not supported in richText tooltip!'); - } - - if (this.el) { - this._zr.remove(this.el); - } - - var textStyleModel = tooltipModel.getModel('textStyle'); - this.el = new ZRText({ - style: { - rich: markupStyleCreator.richTextStyles, - text: content, - lineHeight: 22, - borderWidth: 1, - borderColor: borderColor, - textShadowColor: textStyleModel.get('textShadowColor'), - fill: tooltipModel.get(['textStyle', 'color']), - padding: getPaddingFromTooltipModel(tooltipModel, 'richText'), - verticalAlign: 'top', - align: 'left' - }, - z: tooltipModel.get('z') - }); - each$4(['backgroundColor', 'borderRadius', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'], function (propName) { - _this.el.style[propName] = tooltipModel.get(propName); - }); - each$4(['textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'], function (propName) { - _this.el.style[propName] = textStyleModel.get(propName) || 0; - }); - - this._zr.add(this.el); - - var self = this; - this.el.on('mouseover', function () { - // clear the timeout in hideLater and keep showing tooltip - if (self._enterable) { - clearTimeout(self._hideTimeout); - self._show = true; - } - - self._inContent = true; - }); - this.el.on('mouseout', function () { - if (self._enterable) { - if (self._show) { - self.hideLater(self._hideDelay); - } - } - - self._inContent = false; - }); - }; - - TooltipRichContent.prototype.setEnterable = function (enterable) { - this._enterable = enterable; - }; - - TooltipRichContent.prototype.getSize = function () { - var el = this.el; - var bounding = this.el.getBoundingRect(); // bounding rect does not include shadow. For renderMode richText, - // if overflow, it will be cut. So calculate them accurately. - - var shadowOuterSize = calcShadowOuterSize(el.style); - return [bounding.width + shadowOuterSize.left + shadowOuterSize.right, bounding.height + shadowOuterSize.top + shadowOuterSize.bottom]; - }; - - TooltipRichContent.prototype.moveTo = function (x, y) { - var el = this.el; - - if (el) { - var styleCoord = this._styleCoord; - makeStyleCoord(styleCoord, this._zr, x, y); - x = styleCoord[0]; - y = styleCoord[1]; - var style = el.style; - var borderWidth = mathMaxWith0(style.borderWidth || 0); - var shadowOuterSize = calcShadowOuterSize(style); // rich text x, y do not include border. - - el.x = x + borderWidth + shadowOuterSize.left; - el.y = y + borderWidth + shadowOuterSize.top; - el.markRedraw(); - } - }; - /** - * when `alwaysShowContent` is true, - * move the tooltip after chart resized - */ - - - TooltipRichContent.prototype._moveIfResized = function () { - // The ratio of left to width - var ratioX = this._styleCoord[2]; // The ratio of top to height - - var ratioY = this._styleCoord[3]; - this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); - }; - - TooltipRichContent.prototype.hide = function () { - if (this.el) { - this.el.hide(); - } - - this._show = false; - }; - - TooltipRichContent.prototype.hideLater = function (time) { - if (this._show && !(this._inContent && this._enterable) && !this._alwaysShowContent) { - if (time) { - this._hideDelay = time; // Set show false to avoid invoke hideLater multiple times - - this._show = false; - this._hideTimeout = setTimeout(bind$1(this.hide, this), time); - } else { - this.hide(); - } - } - }; - - TooltipRichContent.prototype.isShow = function () { - return this._show; - }; - - TooltipRichContent.prototype.dispose = function () { - this._zr.remove(this.el); - }; - - return TooltipRichContent; - }(); - - function mathMaxWith0(val) { - return Math.max(0, val); - } - - function calcShadowOuterSize(style) { - var shadowBlur = mathMaxWith0(style.shadowBlur || 0); - var shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0); - var shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0); - return { - left: mathMaxWith0(shadowBlur - shadowOffsetX), - right: mathMaxWith0(shadowBlur + shadowOffsetX), - top: mathMaxWith0(shadowBlur - shadowOffsetY), - bottom: mathMaxWith0(shadowBlur + shadowOffsetY) - }; - } - - function makeStyleCoord(out, zr, zrX, zrY) { - out[0] = zrX; - out[1] = zrY; - out[2] = out[0] / zr.getWidth(); - out[3] = out[1] / zr.getHeight(); - } - - var proxyRect = new Rect({ - shape: { - x: -1, - y: -1, - width: 2, - height: 2 - } - }); - - var TooltipView = - /** @class */ - function (_super) { - __extends(TooltipView, _super); - - function TooltipView() { - var _this = _super !== null && _super.apply(this, arguments) || this; - - _this.type = TooltipView.type; - return _this; - } - - TooltipView.prototype.init = function (ecModel, api) { - if (env.node || !api.getDom()) { - return; - } - - var tooltipModel = ecModel.getComponent('tooltip'); - var renderMode = this._renderMode = getTooltipRenderMode(tooltipModel.get('renderMode')); - this._tooltipContent = renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api, { - appendTo: tooltipModel.get('appendToBody', true) ? 'body' : tooltipModel.get('appendTo', true) - }); - }; - - TooltipView.prototype.render = function (tooltipModel, ecModel, api) { - if (env.node || !api.getDom()) { - return; - } // Reset - - - this.group.removeAll(); - this._tooltipModel = tooltipModel; - this._ecModel = ecModel; - this._api = api; - var tooltipContent = this._tooltipContent; - tooltipContent.update(tooltipModel); - tooltipContent.setEnterable(tooltipModel.get('enterable')); - - this._initGlobalListener(); - - this._keepShow(); // PENDING - // `mousemove` event will be triggered very frequently when the mouse moves fast, - // which causes that the `updatePosition` function was also called frequently. - // In Chrome with devtools open and Firefox, tooltip looks laggy and shakes. See #14695 #16101 - // To avoid frequent triggering, - // consider throttling it in 50ms when transition is enabled - - - if (this._renderMode !== 'richText' && tooltipModel.get('transitionDuration')) { - createOrUpdate(this, '_updatePosition', 50, 'fixRate'); - } else { - clear(this, '_updatePosition'); - } - }; - - TooltipView.prototype._initGlobalListener = function () { - var tooltipModel = this._tooltipModel; - var triggerOn = tooltipModel.get('triggerOn'); - register('itemTooltip', this._api, bind$1(function (currTrigger, e, dispatchAction) { - // If 'none', it is not controlled by mouse totally. - if (triggerOn !== 'none') { - if (triggerOn.indexOf(currTrigger) >= 0) { - this._tryShow(e, dispatchAction); - } else if (currTrigger === 'leave') { - this._hide(dispatchAction); - } - } - }, this)); - }; - - TooltipView.prototype._keepShow = function () { - var tooltipModel = this._tooltipModel; - var ecModel = this._ecModel; - var api = this._api; - var triggerOn = tooltipModel.get('triggerOn'); // Try to keep the tooltip show when refreshing - - if (this._lastX != null && this._lastY != null // When user is willing to control tooltip totally using API, - // self.manuallyShowTip({x, y}) might cause tooltip hide, - // which is not expected. - && triggerOn !== 'none' && triggerOn !== 'click') { - var self_1 = this; - clearTimeout(this._refreshUpdateTimeout); - this._refreshUpdateTimeout = setTimeout(function () { - // Show tip next tick after other charts are rendered - // In case highlight action has wrong result - // FIXME - !api.isDisposed() && self_1.manuallyShowTip(tooltipModel, ecModel, api, { - x: self_1._lastX, - y: self_1._lastY, - dataByCoordSys: self_1._lastDataByCoordSys - }); - }); - } - }; - /** - * Show tip manually by - * dispatchAction({ - * type: 'showTip', - * x: 10, - * y: 10 - * }); - * Or - * dispatchAction({ - * type: 'showTip', - * seriesIndex: 0, - * dataIndex or dataIndexInside or name - * }); - * - * TODO Batch - */ - - - TooltipView.prototype.manuallyShowTip = function (tooltipModel, ecModel, api, payload) { - if (payload.from === this.uid || env.node || !api.getDom()) { - return; - } - - var dispatchAction = makeDispatchAction(payload, api); // Reset ticket - - this._ticket = ''; // When triggered from axisPointer. - - var dataByCoordSys = payload.dataByCoordSys; - var cmptRef = findComponentReference(payload, ecModel, api); - - if (cmptRef) { - var rect = cmptRef.el.getBoundingRect().clone(); - rect.applyTransform(cmptRef.el.transform); - - this._tryShow({ - offsetX: rect.x + rect.width / 2, - offsetY: rect.y + rect.height / 2, - target: cmptRef.el, - position: payload.position, - // When manully trigger, the mouse is not on the el, so we'd better to - // position tooltip on the bottom of the el and display arrow is possible. - positionDefault: 'bottom' - }, dispatchAction); - } else if (payload.tooltip && payload.x != null && payload.y != null) { - var el = proxyRect; - el.x = payload.x; - el.y = payload.y; - el.update(); - getECData(el).tooltipConfig = { - name: null, - option: payload.tooltip - }; // Manually show tooltip while view is not using zrender elements. - - this._tryShow({ - offsetX: payload.x, - offsetY: payload.y, - target: el - }, dispatchAction); - } else if (dataByCoordSys) { - this._tryShow({ - offsetX: payload.x, - offsetY: payload.y, - position: payload.position, - dataByCoordSys: dataByCoordSys, - tooltipOption: payload.tooltipOption - }, dispatchAction); - } else if (payload.seriesIndex != null) { - if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) { - return; - } - - var pointInfo = findPointFromSeries(payload, ecModel); - var cx = pointInfo.point[0]; - var cy = pointInfo.point[1]; - - if (cx != null && cy != null) { - this._tryShow({ - offsetX: cx, - offsetY: cy, - target: pointInfo.el, - position: payload.position, - // When manully trigger, the mouse is not on the el, so we'd better to - // position tooltip on the bottom of the el and display arrow is possible. - positionDefault: 'bottom' - }, dispatchAction); - } - } else if (payload.x != null && payload.y != null) { - // FIXME - // should wrap dispatchAction like `axisPointer/globalListener` ? - api.dispatchAction({ - type: 'updateAxisPointer', - x: payload.x, - y: payload.y - }); - - this._tryShow({ - offsetX: payload.x, - offsetY: payload.y, - position: payload.position, - target: api.getZr().findHover(payload.x, payload.y).target - }, dispatchAction); - } - }; - - TooltipView.prototype.manuallyHideTip = function (tooltipModel, ecModel, api, payload) { - var tooltipContent = this._tooltipContent; - - if (this._tooltipModel) { - tooltipContent.hideLater(this._tooltipModel.get('hideDelay')); - } - - this._lastX = this._lastY = this._lastDataByCoordSys = null; - - if (payload.from !== this.uid) { - this._hide(makeDispatchAction(payload, api)); - } - }; // Be compatible with previous design, that is, when tooltip.type is 'axis' and - // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer - // and tooltip. - - - TooltipView.prototype._manuallyAxisShowTip = function (tooltipModel, ecModel, api, payload) { - var seriesIndex = payload.seriesIndex; - var dataIndex = payload.dataIndex; // @ts-ignore - - var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; - - if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) { - return; - } - - var seriesModel = ecModel.getSeriesByIndex(seriesIndex); - - if (!seriesModel) { - return; - } - - var data = seriesModel.getData(); - var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model], this._tooltipModel); - - if (tooltipCascadedModel.get('trigger') !== 'axis') { - return; - } - - api.dispatchAction({ - type: 'updateAxisPointer', - seriesIndex: seriesIndex, - dataIndex: dataIndex, - position: payload.position - }); - return true; - }; - - TooltipView.prototype._tryShow = function (e, dispatchAction) { - var el = e.target; - var tooltipModel = this._tooltipModel; - - if (!tooltipModel) { - return; - } // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed - - - this._lastX = e.offsetX; - this._lastY = e.offsetY; - var dataByCoordSys = e.dataByCoordSys; - - if (dataByCoordSys && dataByCoordSys.length) { - this._showAxisTooltip(dataByCoordSys, e); - } else if (el) { - var ecData = getECData(el); - - if (ecData.ssrType === 'legend') { - // Don't trigger tooltip for legend tooltip item - return; - } - - this._lastDataByCoordSys = null; - var seriesDispatcher_1; - var cmptDispatcher_1; - findEventDispatcher(el, function (target) { - // Always show item tooltip if mouse is on the element with dataIndex - if (getECData(target).dataIndex != null) { - seriesDispatcher_1 = target; - return true; - } // Tooltip provided directly. Like legend. - - - if (getECData(target).tooltipConfig != null) { - cmptDispatcher_1 = target; - return true; - } - }, true); - - if (seriesDispatcher_1) { - this._showSeriesItemTooltip(e, seriesDispatcher_1, dispatchAction); - } else if (cmptDispatcher_1) { - this._showComponentItemTooltip(e, cmptDispatcher_1, dispatchAction); - } else { - this._hide(dispatchAction); - } - } else { - this._lastDataByCoordSys = null; - - this._hide(dispatchAction); - } - }; - - TooltipView.prototype._showOrMove = function (tooltipModel, cb) { - // showDelay is used in this case: tooltip.enterable is set - // as true. User intent to move mouse into tooltip and click - // something. `showDelay` makes it easier to enter the content - // but tooltip do not move immediately. - var delay = tooltipModel.get('showDelay'); - cb = bind$1(cb, this); - clearTimeout(this._showTimout); - delay > 0 ? this._showTimout = setTimeout(cb, delay) : cb(); - }; - - TooltipView.prototype._showAxisTooltip = function (dataByCoordSys, e) { - var ecModel = this._ecModel; - var globalTooltipModel = this._tooltipModel; - var point = [e.offsetX, e.offsetY]; - var singleTooltipModel = buildTooltipModel([e.tooltipOption], globalTooltipModel); - var renderMode = this._renderMode; - var cbParamsList = []; - var articleMarkup = createTooltipMarkup('section', { - blocks: [], - noHeader: true - }); // Only for legacy: `Serise['formatTooltip']` returns a string. - - var markupTextArrLegacy = []; - var markupStyleCreator = new TooltipMarkupStyleCreator(); - each$4(dataByCoordSys, function (itemCoordSys) { - each$4(itemCoordSys.dataByAxis, function (axisItem) { - var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex); - var axisValue = axisItem.value; - - if (!axisModel || axisValue == null) { - return; - } - - var axisValueLabel = getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); - var axisSectionMarkup = createTooltipMarkup('section', { - header: axisValueLabel, - noHeader: !trim(axisValueLabel), - sortBlocks: true, - blocks: [] - }); - articleMarkup.blocks.push(axisSectionMarkup); - each$4(axisItem.seriesDataIndices, function (idxItem) { - var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); - var dataIndex = idxItem.dataIndexInside; - var cbParams = series.getDataParams(dataIndex); // Can't find data. - - if (cbParams.dataIndex < 0) { - return; - } - - cbParams.axisDim = axisItem.axisDim; - cbParams.axisIndex = axisItem.axisIndex; - cbParams.axisType = axisItem.axisType; - cbParams.axisId = axisItem.axisId; - cbParams.axisValue = getAxisRawValue(axisModel.axis, { - value: axisValue - }); - cbParams.axisValueLabel = axisValueLabel; // Pre-create marker style for makers. Users can assemble richText - // text in `formatter` callback and use those markers style. - - cbParams.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(cbParams.color), renderMode); - var seriesTooltipResult = normalizeTooltipFormatResult(series.formatTooltip(dataIndex, true, null)); - var frag = seriesTooltipResult.frag; - - if (frag) { - var valueFormatter = buildTooltipModel([series], globalTooltipModel).get('valueFormatter'); - axisSectionMarkup.blocks.push(valueFormatter ? extend({ - valueFormatter: valueFormatter - }, frag) : frag); - } - - if (seriesTooltipResult.text) { - markupTextArrLegacy.push(seriesTooltipResult.text); - } - - cbParamsList.push(cbParams); - }); - }); - }); // In most cases, the second axis is displays upper on the first one. - // So we reverse it to look better. - - articleMarkup.blocks.reverse(); - markupTextArrLegacy.reverse(); - var positionExpr = e.position; - var orderMode = singleTooltipModel.get('order'); - var builtMarkupText = buildTooltipMarkup(articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), singleTooltipModel.get('textStyle')); - builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText); - var blockBreak = renderMode === 'richText' ? '\n\n' : '
'; - var allMarkupText = markupTextArrLegacy.join(blockBreak); - - this._showOrMove(singleTooltipModel, function () { - if (this._updateContentNotChangedOnAxis(dataByCoordSys, cbParamsList)) { - this._updatePosition(singleTooltipModel, positionExpr, point[0], point[1], this._tooltipContent, cbParamsList); - } else { - this._showTooltipContent(singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '', point[0], point[1], positionExpr, null, markupStyleCreator); - } - }); // Do not trigger events here, because this branch only be entered - // from dispatchAction. - - }; - - TooltipView.prototype._showSeriesItemTooltip = function (e, dispatcher, dispatchAction) { - var ecModel = this._ecModel; - var ecData = getECData(dispatcher); // Use dataModel in element if possible - // Used when mouseover on a element like markPoint or edge - // In which case, the data is not main data in series. - - var seriesIndex = ecData.seriesIndex; - var seriesModel = ecModel.getSeriesByIndex(seriesIndex); // For example, graph link. - - var dataModel = ecData.dataModel || seriesModel; - var dataIndex = ecData.dataIndex; - var dataType = ecData.dataType; - var data = dataModel.getData(dataType); - var renderMode = this._renderMode; - var positionDefault = e.positionDefault; - var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model], this._tooltipModel, positionDefault ? { - position: positionDefault - } : null); - var tooltipTrigger = tooltipModel.get('trigger'); - - if (tooltipTrigger != null && tooltipTrigger !== 'item') { - return; - } - - var params = dataModel.getDataParams(dataIndex, dataType); - var markupStyleCreator = new TooltipMarkupStyleCreator(); // Pre-create marker style for makers. Users can assemble richText - // text in `formatter` callback and use those markers style. - - params.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(params.color), renderMode); - var seriesTooltipResult = normalizeTooltipFormatResult(dataModel.formatTooltip(dataIndex, false, dataType)); - var orderMode = tooltipModel.get('order'); - var valueFormatter = tooltipModel.get('valueFormatter'); - var frag = seriesTooltipResult.frag; - var markupText = frag ? buildTooltipMarkup(valueFormatter ? extend({ - valueFormatter: valueFormatter - }, frag) : frag, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), tooltipModel.get('textStyle')) : seriesTooltipResult.text; - var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex; - - this._showOrMove(tooltipModel, function () { - this._showTooltipContent(tooltipModel, markupText, params, asyncTicket, e.offsetX, e.offsetY, e.position, e.target, markupStyleCreator); - }); // FIXME - // duplicated showtip if manuallyShowTip is called from dispatchAction. - - - dispatchAction({ - type: 'showTip', - dataIndexInside: dataIndex, - dataIndex: data.getRawIndex(dataIndex), - seriesIndex: seriesIndex, - from: this.uid - }); - }; - - TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) { - var ecData = getECData(el); - var tooltipConfig = ecData.tooltipConfig; - var tooltipOpt = tooltipConfig.option || {}; - - if (isString(tooltipOpt)) { - var content = tooltipOpt; - tooltipOpt = { - content: content, - // Fixed formatter - formatter: content - }; - } - - var tooltipModelCascade = [tooltipOpt]; - - var cmpt = this._ecModel.getComponent(ecData.componentMainType, ecData.componentIndex); - - if (cmpt) { - tooltipModelCascade.push(cmpt); - } // In most cases, component tooltip formatter has different params with series tooltip formatter, - // so that they cannot share the same formatter. Since the global tooltip formatter is used for series - // by convention, we do not use it as the default formatter for component. - - - tooltipModelCascade.push({ - formatter: tooltipOpt.content - }); - var positionDefault = e.positionDefault; - var subTooltipModel = buildTooltipModel(tooltipModelCascade, this._tooltipModel, positionDefault ? { - position: positionDefault - } : null); - var defaultHtml = subTooltipModel.get('content'); - var asyncTicket = Math.random() + ''; // PENDING: this case do not support richText style yet. - - var markupStyleCreator = new TooltipMarkupStyleCreator(); // Do not check whether `trigger` is 'none' here, because `trigger` - // only works on coordinate system. In fact, we have not found case - // that requires setting `trigger` nothing on component yet. - - this._showOrMove(subTooltipModel, function () { - // Use formatterParams from element defined in component - // Avoid users modify it. - var formatterParams = clone$3(subTooltipModel.get('formatterParams') || {}); - - this._showTooltipContent(subTooltipModel, defaultHtml, formatterParams, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator); - }); // If not dispatch showTip, tip may be hide triggered by axis. - - - dispatchAction({ - type: 'showTip', - from: this.uid - }); - }; - - TooltipView.prototype._showTooltipContent = function ( // Use Model insteadof TooltipModel because this model may be from series or other options. - // Instead of top level tooltip. - tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markupStyleCreator) { - // Reset ticket - this._ticket = ''; - - if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) { - return; - } - - var tooltipContent = this._tooltipContent; - tooltipContent.setEnterable(tooltipModel.get('enterable')); - var formatter = tooltipModel.get('formatter'); - positionExpr = positionExpr || tooltipModel.get('position'); - var html = defaultHtml; - - var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'), tooltipModel.get('borderColor')); - - var nearPointColor = nearPoint.color; - - if (formatter) { - if (isString(formatter)) { - var useUTC = tooltipModel.ecModel.get('useUTC'); - var params0 = isArray(params) ? params[0] : params; - var isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0; - html = formatter; - - if (isTimeAxis) { - html = format$1(params0.axisValue, html, useUTC); - } - - html = formatTpl(html, params, true); - } else if (isFunction(formatter)) { - var callback = bind$1(function (cbTicket, html) { - if (cbTicket === this._ticket) { - tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr); - - this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); - } - }, this); - this._ticket = asyncTicket; - html = formatter(params, asyncTicket, callback); - } else { - html = formatter; - } - } - - tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPointColor, positionExpr); - tooltipContent.show(tooltipModel, nearPointColor); - - this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); - }; - - TooltipView.prototype._getNearestPoint = function (point, tooltipDataParams, trigger, borderColor) { - if (trigger === 'axis' || isArray(tooltipDataParams)) { - return { - color: borderColor || (this._renderMode === 'html' ? '#fff' : 'none') - }; - } - - if (!isArray(tooltipDataParams)) { - return { - color: borderColor || tooltipDataParams.color || tooltipDataParams.borderColor - }; - } - }; - - TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, // Mouse x - y, // Mouse y - content, params, el) { - var viewWidth = this._api.getWidth(); - - var viewHeight = this._api.getHeight(); - - positionExpr = positionExpr || tooltipModel.get('position'); - var contentSize = content.getSize(); - var align = tooltipModel.get('align'); - var vAlign = tooltipModel.get('verticalAlign'); - var rect = el && el.getBoundingRect().clone(); - el && rect.applyTransform(el.transform); - - if (isFunction(positionExpr)) { - // Callback of position can be an array or a string specify the position - positionExpr = positionExpr([x, y], params, content.el, rect, { - viewSize: [viewWidth, viewHeight], - contentSize: contentSize.slice() - }); - } - - if (isArray(positionExpr)) { - x = parsePercent(positionExpr[0], viewWidth); - y = parsePercent(positionExpr[1], viewHeight); - } else if (isObject$2(positionExpr)) { - var boxLayoutPosition = positionExpr; - boxLayoutPosition.width = contentSize[0]; - boxLayoutPosition.height = contentSize[1]; - var layoutRect = getLayoutRect(boxLayoutPosition, { - width: viewWidth, - height: viewHeight - }); - x = layoutRect.x; - y = layoutRect.y; - align = null; // When positionExpr is left/top/right/bottom, - // align and verticalAlign will not work. - - vAlign = null; - } // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element - else if (isString(positionExpr) && el) { - var pos = calcTooltipPosition(positionExpr, rect, contentSize, tooltipModel.get('borderWidth')); - x = pos[0]; - y = pos[1]; - } else { - var pos = refixTooltipPosition(x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20); - x = pos[0]; - y = pos[1]; - } - - align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0); - vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0); - - if (shouldTooltipConfine(tooltipModel)) { - var pos = confineTooltipPosition(x, y, content, viewWidth, viewHeight); - x = pos[0]; - y = pos[1]; - } - - content.moveTo(x, y); - }; // FIXME - // Should we remove this but leave this to user? - - - TooltipView.prototype._updateContentNotChangedOnAxis = function (dataByCoordSys, cbParamsList) { - var lastCoordSys = this._lastDataByCoordSys; - var lastCbParamsList = this._cbParamsList; - var contentNotChanged = !!lastCoordSys && lastCoordSys.length === dataByCoordSys.length; - contentNotChanged && each$4(lastCoordSys, function (lastItemCoordSys, indexCoordSys) { - var lastDataByAxis = lastItemCoordSys.dataByAxis || []; - var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {}; - var thisDataByAxis = thisItemCoordSys.dataByAxis || []; - contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length; - contentNotChanged && each$4(lastDataByAxis, function (lastItem, indexAxis) { - var thisItem = thisDataByAxis[indexAxis] || {}; - var lastIndices = lastItem.seriesDataIndices || []; - var newIndices = thisItem.seriesDataIndices || []; - contentNotChanged = contentNotChanged && lastItem.value === thisItem.value && lastItem.axisType === thisItem.axisType && lastItem.axisId === thisItem.axisId && lastIndices.length === newIndices.length; - contentNotChanged && each$4(lastIndices, function (lastIdxItem, j) { - var newIdxItem = newIndices[j]; - contentNotChanged = contentNotChanged && lastIdxItem.seriesIndex === newIdxItem.seriesIndex && lastIdxItem.dataIndex === newIdxItem.dataIndex; - }); // check is cbParams data value changed - - lastCbParamsList && each$4(lastItem.seriesDataIndices, function (idxItem) { - var seriesIdx = idxItem.seriesIndex; - var cbParams = cbParamsList[seriesIdx]; - var lastCbParams = lastCbParamsList[seriesIdx]; - - if (cbParams && lastCbParams && lastCbParams.data !== cbParams.data) { - contentNotChanged = false; - } - }); - }); - }); - this._lastDataByCoordSys = dataByCoordSys; - this._cbParamsList = cbParamsList; - return !!contentNotChanged; - }; - - TooltipView.prototype._hide = function (dispatchAction) { - // Do not directly hideLater here, because this behavior may be prevented - // in dispatchAction when showTip is dispatched. - // FIXME - // duplicated hideTip if manuallyHideTip is called from dispatchAction. - this._lastDataByCoordSys = null; - dispatchAction({ - type: 'hideTip', - from: this.uid - }); - }; - - TooltipView.prototype.dispose = function (ecModel, api) { - if (env.node || !api.getDom()) { - return; - } - - clear(this, '_updatePosition'); - - this._tooltipContent.dispose(); - - unregister('itemTooltip', api); - }; - - TooltipView.type = 'tooltip'; - return TooltipView; - }(ComponentView); - /** - * From top to bottom. (the last one should be globalTooltipModel); - */ - - - function buildTooltipModel(modelCascade, globalTooltipModel, defaultTooltipOption) { - // Last is always tooltip model. - var ecModel = globalTooltipModel.ecModel; - var resultModel; - - if (defaultTooltipOption) { - resultModel = new Model(defaultTooltipOption, ecModel, ecModel); - resultModel = new Model(globalTooltipModel.option, resultModel, ecModel); - } else { - resultModel = globalTooltipModel; - } - - for (var i = modelCascade.length - 1; i >= 0; i--) { - var tooltipOpt = modelCascade[i]; - - if (tooltipOpt) { - if (tooltipOpt instanceof Model) { - tooltipOpt = tooltipOpt.get('tooltip', true); - } // In each data item tooltip can be simply write: - // { - // value: 10, - // tooltip: 'Something you need to know' - // } - - - if (isString(tooltipOpt)) { - tooltipOpt = { - formatter: tooltipOpt - }; - } - - if (tooltipOpt) { - resultModel = new Model(tooltipOpt, resultModel, ecModel); - } - } - } - - return resultModel; - } - - function makeDispatchAction(payload, api) { - return payload.dispatchAction || bind$1(api.dispatchAction, api); - } - - function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) { - var size = content.getSize(); - var width = size[0]; - var height = size[1]; - - if (gapH != null) { - // Add extra 2 pixels for this case: - // At present the "values" in default tooltip are using CSS `float: right`. - // When the right edge of the tooltip box is on the right side of the - // viewport, the `float` layout might push the "values" to the second line. - if (x + width + gapH + 2 > viewWidth) { - x -= width + gapH; - } else { - x += gapH; - } - } - - if (gapV != null) { - if (y + height + gapV > viewHeight) { - y -= height + gapV; - } else { - y += gapV; - } - } - - return [x, y]; - } - - function confineTooltipPosition(x, y, content, viewWidth, viewHeight) { - var size = content.getSize(); - var width = size[0]; - var height = size[1]; - x = Math.min(x + width, viewWidth) - width; - y = Math.min(y + height, viewHeight) - height; - x = Math.max(x, 0); - y = Math.max(y, 0); - return [x, y]; - } - - function calcTooltipPosition(position, rect, contentSize, borderWidth) { - var domWidth = contentSize[0]; - var domHeight = contentSize[1]; - var offset = Math.ceil(Math.SQRT2 * borderWidth) + 8; - var x = 0; - var y = 0; - var rectWidth = rect.width; - var rectHeight = rect.height; - - switch (position) { - case 'inside': - x = rect.x + rectWidth / 2 - domWidth / 2; - y = rect.y + rectHeight / 2 - domHeight / 2; - break; - - case 'top': - x = rect.x + rectWidth / 2 - domWidth / 2; - y = rect.y - domHeight - offset; - break; - - case 'bottom': - x = rect.x + rectWidth / 2 - domWidth / 2; - y = rect.y + rectHeight + offset; - break; - - case 'left': - x = rect.x - domWidth - offset; - y = rect.y + rectHeight / 2 - domHeight / 2; - break; - - case 'right': - x = rect.x + rectWidth + offset; - y = rect.y + rectHeight / 2 - domHeight / 2; - } - - return [x, y]; - } - - function isCenterAlign(align) { - return align === 'center' || align === 'middle'; - } - /** - * Find target component by payload like: - * ```js - * { legendId: 'some_id', name: 'xxx' } - * { toolboxIndex: 1, name: 'xxx' } - * { geoName: 'some_name', name: 'xxx' } - * ``` - * PENDING: at present only - * - * If not found, return null/undefined. - */ - - - function findComponentReference(payload, ecModel, api) { - var queryOptionMap = preParseFinder(payload).queryOptionMap; - var componentMainType = queryOptionMap.keys()[0]; - - if (!componentMainType || componentMainType === 'series') { - return; - } - - var queryResult = queryReferringComponents(ecModel, componentMainType, queryOptionMap.get(componentMainType), { - useDefault: false, - enableAll: false, - enableNone: false - }); - var model = queryResult.models[0]; - - if (!model) { - return; - } - - var view = api.getViewOfComponentModel(model); - var el; - view.group.traverse(function (subEl) { - var tooltipConfig = getECData(subEl).tooltipConfig; - - if (tooltipConfig && tooltipConfig.name === payload.name) { - el = subEl; - return true; // stop - } - }); - - if (el) { - return { - componentMainType: componentMainType, - componentIndex: model.componentIndex, - el: el - }; - } - } - - function install$1(registers) { - use(install$2); - registers.registerComponentModel(TooltipModel); - registers.registerComponentView(TooltipView); - /** - * @action - * @property {string} type - * @property {number} seriesIndex - * @property {number} dataIndex - * @property {number} [x] - * @property {number} [y] - */ - - registers.registerAction({ - type: 'showTip', - event: 'showTip', - update: 'tooltip:manuallyShowTip' - }, noop); - registers.registerAction({ - type: 'hideTip', - event: 'hideTip', - update: 'tooltip:manuallyHideTip' - }, noop); - } - - use(install$1); - use(install$a); - var RELATIONAL_EXPRESSION_OP_ALIAS_MAP = { - value: 'eq', - // PENDING: not good for literal semantic? - '<': 'lt', - '<=': 'lte', - '>': 'gt', - '>=': 'gte', - '=': 'eq', - '!=': 'ne', - '<>': 'ne' // Might be misleading for sake of the difference between '==' and '===', - // so don't support them. - // '==': 'eq', - // '===': 'seq', - // '!==': 'sne' - // PENDING: Whether support some common alias "ge", "le", "neq"? - // ge: 'gte', - // le: 'lte', - // neq: 'ne', - - }; // type RelationalExpressionOpEvaluate = (tarVal: unknown, condVal: unknown) => boolean; - - var RegExpEvaluator = - /** @class */ - function () { - function RegExpEvaluator(rVal) { - // Support condVal: RegExp | string - var condValue = this._condVal = isString(rVal) ? new RegExp(rVal) : isRegExp(rVal) ? rVal : null; - - if (condValue == null) { - var errMsg = ''; - { - errMsg = makePrintable('Illegal regexp', rVal, 'in'); - } - throwError(errMsg); - } - } - - RegExpEvaluator.prototype.evaluate = function (lVal) { - var type = typeof lVal; - return isString(type) ? this._condVal.test(lVal) : isNumber(type) ? this._condVal.test(lVal + '') : false; - }; - - return RegExpEvaluator; - }(); - - var ConstConditionInternal = - /** @class */ - function () { - function ConstConditionInternal() {} - - ConstConditionInternal.prototype.evaluate = function () { - return this.value; - }; - - return ConstConditionInternal; - }(); - - var AndConditionInternal = - /** @class */ - function () { - function AndConditionInternal() {} - - AndConditionInternal.prototype.evaluate = function () { - var children = this.children; - - for (var i = 0; i < children.length; i++) { - if (!children[i].evaluate()) { - return false; - } - } - - return true; - }; - - return AndConditionInternal; - }(); - - var OrConditionInternal = - /** @class */ - function () { - function OrConditionInternal() {} - - OrConditionInternal.prototype.evaluate = function () { - var children = this.children; - - for (var i = 0; i < children.length; i++) { - if (children[i].evaluate()) { - return true; - } - } - - return false; - }; - - return OrConditionInternal; - }(); - - var NotConditionInternal = - /** @class */ - function () { - function NotConditionInternal() {} - - NotConditionInternal.prototype.evaluate = function () { - return !this.child.evaluate(); - }; - - return NotConditionInternal; - }(); - - var RelationalConditionInternal = - /** @class */ - function () { - function RelationalConditionInternal() {} - - RelationalConditionInternal.prototype.evaluate = function () { - var needParse = !!this.valueParser; // Call getValue with no `this`. - - var getValue = this.getValue; - var tarValRaw = getValue(this.valueGetterParam); - var tarValParsed = needParse ? this.valueParser(tarValRaw) : null; // Relational cond follow "and" logic internally. - - for (var i = 0; i < this.subCondList.length; i++) { - if (!this.subCondList[i].evaluate(needParse ? tarValParsed : tarValRaw)) { - return false; - } - } - - return true; - }; - - return RelationalConditionInternal; - }(); - - function parseOption(exprOption, getters) { - if (exprOption === true || exprOption === false) { - var cond = new ConstConditionInternal(); - cond.value = exprOption; - return cond; - } - - var errMsg = ''; - - if (!isObjectNotArray(exprOption)) { - { - errMsg = makePrintable('Illegal config. Expect a plain object but actually', exprOption); - } - throwError(errMsg); - } - - if (exprOption.and) { - return parseAndOrOption('and', exprOption, getters); - } else if (exprOption.or) { - return parseAndOrOption('or', exprOption, getters); - } else if (exprOption.not) { - return parseNotOption(exprOption, getters); - } - - return parseRelationalOption(exprOption, getters); - } - - function parseAndOrOption(op, exprOption, getters) { - var subOptionArr = exprOption[op]; - var errMsg = ''; - { - errMsg = makePrintable('"and"/"or" condition should only be `' + op + ': [...]` and must not be empty array.', 'Illegal condition:', exprOption); - } - - if (!isArray(subOptionArr)) { - throwError(errMsg); - } - - if (!subOptionArr.length) { - throwError(errMsg); - } - - var cond = op === 'and' ? new AndConditionInternal() : new OrConditionInternal(); - cond.children = map$1(subOptionArr, function (subOption) { - return parseOption(subOption, getters); - }); - - if (!cond.children.length) { - throwError(errMsg); - } - - return cond; - } - - function parseNotOption(exprOption, getters) { - var subOption = exprOption.not; - var errMsg = ''; - { - errMsg = makePrintable('"not" condition should only be `not: {}`.', 'Illegal condition:', exprOption); - } - - if (!isObjectNotArray(subOption)) { - throwError(errMsg); - } - - var cond = new NotConditionInternal(); - cond.child = parseOption(subOption, getters); - - if (!cond.child) { - throwError(errMsg); - } - - return cond; - } - - function parseRelationalOption(exprOption, getters) { - var errMsg = ''; - var valueGetterParam = getters.prepareGetValue(exprOption); - var subCondList = []; - var exprKeys = keys(exprOption); - var parserName = exprOption.parser; - var valueParser = parserName ? getRawValueParser(parserName) : null; - - for (var i = 0; i < exprKeys.length; i++) { - var keyRaw = exprKeys[i]; - - if (keyRaw === 'parser' || getters.valueGetterAttrMap.get(keyRaw)) { - continue; - } - - var op = hasOwn(RELATIONAL_EXPRESSION_OP_ALIAS_MAP, keyRaw) ? RELATIONAL_EXPRESSION_OP_ALIAS_MAP[keyRaw] : keyRaw; - var condValueRaw = exprOption[keyRaw]; - var condValueParsed = valueParser ? valueParser(condValueRaw) : condValueRaw; - var evaluator = createFilterComparator(op, condValueParsed) || op === 'reg' && new RegExpEvaluator(condValueParsed); - - if (!evaluator) { - { - errMsg = makePrintable('Illegal relational operation: "' + keyRaw + '" in condition:', exprOption); - } - throwError(errMsg); - } - - subCondList.push(evaluator); - } - - if (!subCondList.length) { - { - errMsg = makePrintable('Relational condition must have at least one operator.', 'Illegal condition:', exprOption); - } // No relational operator always disabled in case of dangers result. - - throwError(errMsg); - } - - var cond = new RelationalConditionInternal(); - cond.valueGetterParam = valueGetterParam; - cond.valueParser = valueParser; - cond.getValue = getters.getValue; - cond.subCondList = subCondList; - return cond; - } - - function isObjectNotArray(val) { - return isObject$2(val) && !isArrayLike(val); - } - - var ConditionalExpressionParsed = - /** @class */ - function () { - function ConditionalExpressionParsed(exprOption, getters) { - this._cond = parseOption(exprOption, getters); - } - - ConditionalExpressionParsed.prototype.evaluate = function () { - return this._cond.evaluate(); - }; - - return ConditionalExpressionParsed; - }(); - - function parseConditionalExpression(exprOption, getters) { - return new ConditionalExpressionParsed(exprOption, getters); - } - - var filterTransform = { - type: 'echarts:filter', - // PENDING: enhance to filter by index rather than create new data - transform: function (params) { - // [Caveat] Fail-Fast: - // Do not return the whole dataset unless user config indicates it explicitly. - // For example, if no condition is specified by mistake, returning an empty result - // is better than returning the entire raw source for the user to find the mistake. - var upstream = params.upstream; - var rawItem; - var condition = parseConditionalExpression(params.config, { - valueGetterAttrMap: createHashMap({ - dimension: true - }), - prepareGetValue: function (exprOption) { - var errMsg = ''; - var dimLoose = exprOption.dimension; - - if (!hasOwn(exprOption, 'dimension')) { - { - errMsg = makePrintable('Relation condition must has prop "dimension" specified.', 'Illegal condition:', exprOption); - } - throwError(errMsg); - } - - var dimInfo = upstream.getDimensionInfo(dimLoose); - - if (!dimInfo) { - { - errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal condition:', exprOption, '.\n'); - } - throwError(errMsg); - } - - return { - dimIdx: dimInfo.index - }; - }, - getValue: function (param) { - return upstream.retrieveValueFromItem(rawItem, param.dimIdx); - } - }); - var resultData = []; - - for (var i = 0, len = upstream.count(); i < len; i++) { - rawItem = upstream.getRawDataItem(i); - - if (condition.evaluate()) { - resultData.push(rawItem); - } - } - - return { - data: resultData - }; - } - }; - var sampleLog = ''; - { - sampleLog = ['Valid config is like:', '{ dimension: "age", order: "asc" }', 'or [{ dimension: "age", order: "asc"], { dimension: "date", order: "desc" }]'].join(' '); - } - var sortTransform = { - type: 'echarts:sort', - transform: function (params) { - var upstream = params.upstream; - var config = params.config; - var errMsg = ''; // Normalize - // const orderExprList: OrderExpression[] = isArray(config[0]) - // ? config as OrderExpression[] - // : [config as OrderExpression]; - - var orderExprList = normalizeToArray(config); - - if (!orderExprList.length) { - { - errMsg = 'Empty `config` in sort transform.'; - } - throwError(errMsg); - } - - var orderDefList = []; - each$4(orderExprList, function (orderExpr) { - var dimLoose = orderExpr.dimension; - var order = orderExpr.order; - var parserName = orderExpr.parser; - var incomparable = orderExpr.incomparable; - - if (dimLoose == null) { - { - errMsg = 'Sort transform config must has "dimension" specified.' + sampleLog; - } - throwError(errMsg); - } - - if (order !== 'asc' && order !== 'desc') { - { - errMsg = 'Sort transform config must has "order" specified.' + sampleLog; - } - throwError(errMsg); - } - - if (incomparable && incomparable !== 'min' && incomparable !== 'max') { - var errMsg_1 = ''; - { - errMsg_1 = 'incomparable must be "min" or "max" rather than "' + incomparable + '".'; - } - throwError(errMsg_1); - } - - if (order !== 'asc' && order !== 'desc') { - var errMsg_2 = ''; - { - errMsg_2 = 'order must be "asc" or "desc" rather than "' + order + '".'; - } - throwError(errMsg_2); - } - - var dimInfo = upstream.getDimensionInfo(dimLoose); - - if (!dimInfo) { - { - errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal config:', orderExpr, '.\n'); - } - throwError(errMsg); - } - - var parser = parserName ? getRawValueParser(parserName) : null; - - if (parserName && !parser) { - { - errMsg = makePrintable('Invalid parser name ' + parserName + '.\n', 'Illegal config:', orderExpr, '.\n'); - } - throwError(errMsg); - } - - orderDefList.push({ - dimIdx: dimInfo.index, - parser: parser, - comparator: new SortOrderComparator(order, incomparable) - }); - }); // TODO: support it? - - var sourceFormat = upstream.sourceFormat; - - if (sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS) { - { - errMsg = 'sourceFormat "' + sourceFormat + '" is not supported yet'; - } - throwError(errMsg); - } // Other upstream format are all array. - - - var resultData = []; - - for (var i = 0, len = upstream.count(); i < len; i++) { - resultData.push(upstream.getRawDataItem(i)); - } - - resultData.sort(function (item0, item1) { - for (var i = 0; i < orderDefList.length; i++) { - var orderDef = orderDefList[i]; - var val0 = upstream.retrieveValueFromItem(item0, orderDef.dimIdx); - var val1 = upstream.retrieveValueFromItem(item1, orderDef.dimIdx); - - if (orderDef.parser) { - val0 = orderDef.parser(val0); - val1 = orderDef.parser(val1); - } - - var result = orderDef.comparator.evaluate(val0, val1); - - if (result !== 0) { - return result; - } - } - - return 0; - }); - return { - data: resultData - }; - } - }; - - function install(registers) { - registers.registerTransform(filterTransform); - registers.registerTransform(sortTransform); - } - - use(install); - var mathSin = Math.sin; - var mathCos = Math.cos; - var PI = Math.PI; - var PI2 = Math.PI * 2; - var degree = 180 / PI; - - var SVGPathRebuilder = function () { - function SVGPathRebuilder() {} - - SVGPathRebuilder.prototype.reset = function (precision) { - this._start = true; - this._d = []; - this._str = ''; - this._p = Math.pow(10, precision || 4); - }; - - SVGPathRebuilder.prototype.moveTo = function (x, y) { - this._add('M', x, y); - }; - - SVGPathRebuilder.prototype.lineTo = function (x, y) { - this._add('L', x, y); - }; - - SVGPathRebuilder.prototype.bezierCurveTo = function (x, y, x2, y2, x3, y3) { - this._add('C', x, y, x2, y2, x3, y3); - }; - - SVGPathRebuilder.prototype.quadraticCurveTo = function (x, y, x2, y2) { - this._add('Q', x, y, x2, y2); - }; - - SVGPathRebuilder.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { - this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise); - }; - - SVGPathRebuilder.prototype.ellipse = function (cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise) { - var dTheta = endAngle - startAngle; - var clockwise = !anticlockwise; - var dThetaPositive = Math.abs(dTheta); - var isCircle = isAroundZero(dThetaPositive - PI2) || (clockwise ? dTheta >= PI2 : -dTheta >= PI2); - var unifiedTheta = dTheta > 0 ? dTheta % PI2 : dTheta % PI2 + PI2; - var large = false; - - if (isCircle) { - large = true; - } else if (isAroundZero(dThetaPositive)) { - large = false; - } else { - large = unifiedTheta >= PI === !!clockwise; - } - - var x0 = cx + rx * mathCos(startAngle); - var y0 = cy + ry * mathSin(startAngle); - - if (this._start) { - this._add('M', x0, y0); - } - - var xRot = Math.round(psi * degree); - - if (isCircle) { - var p = 1 / this._p; - var dTheta_1 = (clockwise ? 1 : -1) * (PI2 - p); - - this._add('A', rx, ry, xRot, 1, +clockwise, cx + rx * mathCos(startAngle + dTheta_1), cy + ry * mathSin(startAngle + dTheta_1)); - - if (p > 1e-2) { - this._add('A', rx, ry, xRot, 0, +clockwise, x0, y0); - } - } else { - var x = cx + rx * mathCos(endAngle); - var y = cy + ry * mathSin(endAngle); - - this._add('A', rx, ry, xRot, +large, +clockwise, x, y); - } - }; - - SVGPathRebuilder.prototype.rect = function (x, y, w, h) { - this._add('M', x, y); - - this._add('l', w, 0); - - this._add('l', 0, h); - - this._add('l', -w, 0); - - this._add('Z'); - }; - - SVGPathRebuilder.prototype.closePath = function () { - if (this._d.length > 0) { - this._add('Z'); - } - }; - - SVGPathRebuilder.prototype._add = function (cmd, a, b, c, d, e, f, g, h) { - var vals = []; - var p = this._p; - - for (var i = 1; i < arguments.length; i++) { - var val = arguments[i]; - - if (isNaN(val)) { - this._invalid = true; - return; - } - - vals.push(Math.round(val * p) / p); - } - - this._d.push(cmd + vals.join(' ')); - - this._start = cmd === 'Z'; - }; - - SVGPathRebuilder.prototype.generateStr = function () { - this._str = this._invalid ? '' : this._d.join(''); - this._d = []; - }; - - SVGPathRebuilder.prototype.getStr = function () { - return this._str; - }; - - return SVGPathRebuilder; - }(); - - var NONE = 'none'; - var mathRound = Math.round; - - function pathHasFill(style) { - var fill = style.fill; - return fill != null && fill !== NONE; - } - - function pathHasStroke(style) { - var stroke = style.stroke; - return stroke != null && stroke !== NONE; - } - - var strokeProps = ['lineCap', 'miterLimit', 'lineJoin']; - var svgStrokeProps = map$1(strokeProps, function (prop) { - return "stroke-" + prop.toLowerCase(); - }); - - function mapStyleToAttrs(updateAttr, style, el, forceUpdate) { - var opacity = style.opacity == null ? 1 : style.opacity; - - if (el instanceof ZRImage) { - updateAttr('opacity', opacity); - return; - } - - if (pathHasFill(style)) { - var fill = normalizeColor(style.fill); - updateAttr('fill', fill.color); - var fillOpacity = style.fillOpacity != null ? style.fillOpacity * fill.opacity * opacity : fill.opacity * opacity; - - if (forceUpdate || fillOpacity < 1) { - updateAttr('fill-opacity', fillOpacity); - } - } else { - updateAttr('fill', NONE); - } - - if (pathHasStroke(style)) { - var stroke = normalizeColor(style.stroke); - updateAttr('stroke', stroke.color); - var strokeScale = style.strokeNoScale ? el.getLineScale() : 1; - var strokeWidth = strokeScale ? (style.lineWidth || 0) / strokeScale : 0; - var strokeOpacity = style.strokeOpacity != null ? style.strokeOpacity * stroke.opacity * opacity : stroke.opacity * opacity; - var strokeFirst = style.strokeFirst; - - if (forceUpdate || strokeWidth !== 1) { - updateAttr('stroke-width', strokeWidth); - } - - if (forceUpdate || strokeFirst) { - updateAttr('paint-order', strokeFirst ? 'stroke' : 'fill'); - } - - if (forceUpdate || strokeOpacity < 1) { - updateAttr('stroke-opacity', strokeOpacity); - } - - if (style.lineDash) { - var _a = getLineDash(el), - lineDash = _a[0], - lineDashOffset = _a[1]; - - if (lineDash) { - lineDashOffset = mathRound(lineDashOffset || 0); - updateAttr('stroke-dasharray', lineDash.join(',')); - - if (lineDashOffset || forceUpdate) { - updateAttr('stroke-dashoffset', lineDashOffset); - } - } - } else if (forceUpdate) { - updateAttr('stroke-dasharray', NONE); - } - - for (var i = 0; i < strokeProps.length; i++) { - var propName = strokeProps[i]; - - if (forceUpdate || style[propName] !== DEFAULT_PATH_STYLE[propName]) { - var val = style[propName] || DEFAULT_PATH_STYLE[propName]; - val && updateAttr(svgStrokeProps[i], val); - } - } - } else if (forceUpdate) { - updateAttr('stroke', NONE); - } - } - - var SVGNS = 'http://www.w3.org/2000/svg'; - var XLINKNS = 'http://www.w3.org/1999/xlink'; - var XMLNS = 'http://www.w3.org/2000/xmlns/'; - var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'; - var META_DATA_PREFIX = 'ecmeta_'; - - function createElement(name) { - return document.createElementNS(SVGNS, name); - } - - function createVNode(tag, key, attrs, children, text) { - return { - tag: tag, - attrs: attrs || {}, - children: children, - text: text, - key: key - }; - } - - function createElementOpen(name, attrs) { - var attrsStr = []; - - if (attrs) { - for (var key in attrs) { - var val = attrs[key]; - var part = key; - - if (val === false) { - continue; - } else if (val !== true && val != null) { - part += "=\"" + val + "\""; - } - - attrsStr.push(part); - } - } - - return "<" + name + " " + attrsStr.join(' ') + ">"; - } - - function createElementClose(name) { - return ""; - } - - function vNodeToString(el, opts) { - opts = opts || {}; - var S = opts.newline ? '\n' : ''; - - function convertElToString(el) { - var children = el.children, - tag = el.tag, - attrs = el.attrs, - text = el.text; - return createElementOpen(tag, attrs) + (tag !== 'style' ? encodeHTML(text) : text || '') + (children ? "" + S + map$1(children, function (child) { - return convertElToString(child); - }).join(S) + S : '') + createElementClose(tag); - } - - return convertElToString(el); - } - - function getCssString(selectorNodes, animationNodes, opts) { - opts = opts || {}; - var S = opts.newline ? '\n' : ''; - var bracketBegin = " {" + S; - var bracketEnd = S + "}"; - var selectors = map$1(keys(selectorNodes), function (className) { - return className + bracketBegin + map$1(keys(selectorNodes[className]), function (attrName) { - return attrName + ":" + selectorNodes[className][attrName] + ";"; - }).join(S) + bracketEnd; - }).join(S); - var animations = map$1(keys(animationNodes), function (animationName) { - return "@keyframes " + animationName + bracketBegin + map$1(keys(animationNodes[animationName]), function (percent) { - return percent + bracketBegin + map$1(keys(animationNodes[animationName][percent]), function (attrName) { - var val = animationNodes[animationName][percent][attrName]; - - if (attrName === 'd') { - val = "path(\"" + val + "\")"; - } - - return attrName + ":" + val + ";"; - }).join(S) + bracketEnd; - }).join(S) + bracketEnd; - }).join(S); - - if (!selectors && !animations) { - return ''; - } - - return [''].join(S); - } - - function createBrushScope(zrId) { - return { - zrId: zrId, - shadowCache: {}, - patternCache: {}, - gradientCache: {}, - clipPathCache: {}, - defs: {}, - cssNodes: {}, - cssAnims: {}, - cssStyleCache: {}, - cssAnimIdx: 0, - shadowIdx: 0, - gradientIdx: 0, - patternIdx: 0, - clipPathIdx: 0 - }; - } - - function createSVGVNode(width, height, children, useViewBox) { - return createVNode('svg', 'root', { - 'width': width, - 'height': height, - 'xmlns': SVGNS, - 'xmlns:xlink': XLINKNS, - 'version': '1.1', - 'baseProfile': 'full', - 'viewBox': useViewBox ? "0 0 " + width + " " + height : false - }, children); - } - - var cssClassIdx = 0; - - function getClassId() { - return cssClassIdx++; - } - - var EASING_MAP = { - cubicIn: '0.32,0,0.67,0', - cubicOut: '0.33,1,0.68,1', - cubicInOut: '0.65,0,0.35,1', - quadraticIn: '0.11,0,0.5,0', - quadraticOut: '0.5,1,0.89,1', - quadraticInOut: '0.45,0,0.55,1', - quarticIn: '0.5,0,0.75,0', - quarticOut: '0.25,1,0.5,1', - quarticInOut: '0.76,0,0.24,1', - quinticIn: '0.64,0,0.78,0', - quinticOut: '0.22,1,0.36,1', - quinticInOut: '0.83,0,0.17,1', - sinusoidalIn: '0.12,0,0.39,0', - sinusoidalOut: '0.61,1,0.88,1', - sinusoidalInOut: '0.37,0,0.63,1', - exponentialIn: '0.7,0,0.84,0', - exponentialOut: '0.16,1,0.3,1', - exponentialInOut: '0.87,0,0.13,1', - circularIn: '0.55,0,1,0.45', - circularOut: '0,0.55,0.45,1', - circularInOut: '0.85,0,0.15,1' - }; - var transformOriginKey = 'transform-origin'; - - function buildPathString(el, kfShape, path) { - var shape = extend({}, el.shape); - extend(shape, kfShape); - el.buildPath(path, shape); - var svgPathBuilder = new SVGPathRebuilder(); - svgPathBuilder.reset(getPathPrecision(el)); - path.rebuildPath(svgPathBuilder, 1); - svgPathBuilder.generateStr(); - return svgPathBuilder.getStr(); - } - - function setTransformOrigin(target, transform) { - var originX = transform.originX, - originY = transform.originY; - - if (originX || originY) { - target[transformOriginKey] = originX + "px " + originY + "px"; - } - } - - var ANIMATE_STYLE_MAP = { - fill: 'fill', - opacity: 'opacity', - lineWidth: 'stroke-width', - lineDashOffset: 'stroke-dashoffset' - }; - - function addAnimation(cssAnim, scope) { - var animationName = scope.zrId + '-ani-' + scope.cssAnimIdx++; - scope.cssAnims[animationName] = cssAnim; - return animationName; - } - - function createCompoundPathCSSAnimation(el, attrs, scope) { - var paths = el.shape.paths; - var composedAnim = {}; - var cssAnimationCfg; - var cssAnimationName; - each$4(paths, function (path) { - var subScope = createBrushScope(scope.zrId); - subScope.animation = true; - createCSSAnimation(path, {}, subScope, true); - var cssAnims = subScope.cssAnims; - var cssNodes = subScope.cssNodes; - var animNames = keys(cssAnims); - var len = animNames.length; - - if (!len) { - return; - } - - cssAnimationName = animNames[len - 1]; - var lastAnim = cssAnims[cssAnimationName]; - - for (var percent in lastAnim) { - var kf = lastAnim[percent]; - composedAnim[percent] = composedAnim[percent] || { - d: '' - }; - composedAnim[percent].d += kf.d || ''; - } - - for (var className in cssNodes) { - var val = cssNodes[className].animation; - - if (val.indexOf(cssAnimationName) >= 0) { - cssAnimationCfg = val; - } - } - }); - - if (!cssAnimationCfg) { - return; - } - - attrs.d = false; - var animationName = addAnimation(composedAnim, scope); - return cssAnimationCfg.replace(cssAnimationName, animationName); - } - - function getEasingFunc(easing) { - return isString(easing) ? EASING_MAP[easing] ? "cubic-bezier(" + EASING_MAP[easing] + ")" : createCubicEasingFunc(easing) ? easing : '' : ''; - } - - function createCSSAnimation(el, attrs, scope, onlyShape) { - var animators = el.animators; - var len = animators.length; - var cssAnimations = []; - - if (el instanceof CompoundPath) { - var animationCfg = createCompoundPathCSSAnimation(el, attrs, scope); - - if (animationCfg) { - cssAnimations.push(animationCfg); - } else if (!len) { - return; - } - } else if (!len) { - return; - } - - var groupAnimators = {}; - - for (var i = 0; i < len; i++) { - var animator = animators[i]; - var cfgArr = [animator.getMaxTime() / 1000 + 's']; - var easing = getEasingFunc(animator.getClip().easing); - var delay = animator.getDelay(); - - if (easing) { - cfgArr.push(easing); - } else { - cfgArr.push('linear'); - } - - if (delay) { - cfgArr.push(delay / 1000 + 's'); - } - - if (animator.getLoop()) { - cfgArr.push('infinite'); - } - - var cfg = cfgArr.join(' '); - groupAnimators[cfg] = groupAnimators[cfg] || [cfg, []]; - groupAnimators[cfg][1].push(animator); - } - - function createSingleCSSAnimation(groupAnimator) { - var animators = groupAnimator[1]; - var len = animators.length; - var transformKfs = {}; - var shapeKfs = {}; - var finalKfs = {}; - var animationTimingFunctionAttrName = 'animation-timing-function'; - - function saveAnimatorTrackToCssKfs(animator, cssKfs, toCssAttrName) { - var tracks = animator.getTracks(); - var maxTime = animator.getMaxTime(); - - for (var k = 0; k < tracks.length; k++) { - var track = tracks[k]; - - if (track.needsAnimate()) { - var kfs = track.keyframes; - var attrName = track.propName; - toCssAttrName && (attrName = toCssAttrName(attrName)); - - if (attrName) { - for (var i = 0; i < kfs.length; i++) { - var kf = kfs[i]; - var percent = Math.round(kf.time / maxTime * 100) + '%'; - var kfEasing = getEasingFunc(kf.easing); - var rawValue = kf.rawValue; - - if (isString(rawValue) || isNumber(rawValue)) { - cssKfs[percent] = cssKfs[percent] || {}; - cssKfs[percent][attrName] = kf.rawValue; - - if (kfEasing) { - cssKfs[percent][animationTimingFunctionAttrName] = kfEasing; - } - } - } - } - } - } - } - - for (var i = 0; i < len; i++) { - var animator = animators[i]; - var targetProp = animator.targetName; - - if (!targetProp) { - !onlyShape && saveAnimatorTrackToCssKfs(animator, transformKfs); - } else if (targetProp === 'shape') { - saveAnimatorTrackToCssKfs(animator, shapeKfs); - } - } - - for (var percent in transformKfs) { - var transform = {}; - copyTransform(transform, el); - extend(transform, transformKfs[percent]); - var str = getSRTTransformString(transform); - var timingFunction = transformKfs[percent][animationTimingFunctionAttrName]; - finalKfs[percent] = str ? { - transform: str - } : {}; - setTransformOrigin(finalKfs[percent], transform); - - if (timingFunction) { - finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; - } - } - - var path; - var canAnimateShape = true; - - for (var percent in shapeKfs) { - finalKfs[percent] = finalKfs[percent] || {}; - var isFirst = !path; - var timingFunction = shapeKfs[percent][animationTimingFunctionAttrName]; - - if (isFirst) { - path = new PathProxy(); - } - - var len_1 = path.len(); - path.reset(); - finalKfs[percent].d = buildPathString(el, shapeKfs[percent], path); - var newLen = path.len(); - - if (!isFirst && len_1 !== newLen) { - canAnimateShape = false; - break; - } - - if (timingFunction) { - finalKfs[percent][animationTimingFunctionAttrName] = timingFunction; - } - } - - if (!canAnimateShape) { - for (var percent in finalKfs) { - delete finalKfs[percent].d; - } - } - - if (!onlyShape) { - for (var i = 0; i < len; i++) { - var animator = animators[i]; - var targetProp = animator.targetName; - - if (targetProp === 'style') { - saveAnimatorTrackToCssKfs(animator, finalKfs, function (propName) { - return ANIMATE_STYLE_MAP[propName]; - }); - } - } - } - - var percents = keys(finalKfs); - var allTransformOriginSame = true; - var transformOrigin; - - for (var i = 1; i < percents.length; i++) { - var p0 = percents[i - 1]; - var p1 = percents[i]; - - if (finalKfs[p0][transformOriginKey] !== finalKfs[p1][transformOriginKey]) { - allTransformOriginSame = false; - break; - } - - transformOrigin = finalKfs[p0][transformOriginKey]; - } - - if (allTransformOriginSame && transformOrigin) { - for (var percent in finalKfs) { - if (finalKfs[percent][transformOriginKey]) { - delete finalKfs[percent][transformOriginKey]; - } - } - - attrs[transformOriginKey] = transformOrigin; - } - - if (filter(percents, function (percent) { - return keys(finalKfs[percent]).length > 0; - }).length) { - var animationName = addAnimation(finalKfs, scope); - return animationName + " " + groupAnimator[0] + " both"; - } - } - - for (var key in groupAnimators) { - var animationCfg = createSingleCSSAnimation(groupAnimators[key]); - - if (animationCfg) { - cssAnimations.push(animationCfg); - } - } - - if (cssAnimations.length) { - var className = scope.zrId + '-cls-' + getClassId(); - scope.cssNodes['.' + className] = { - animation: cssAnimations.join(',') - }; - attrs["class"] = className; - } - } - - function createCSSEmphasis(el, attrs, scope) { - if (!el.ignore) { - if (el.isSilent()) { - var style = { - 'pointer-events': 'none' - }; - setClassAttribute(style, attrs, scope, true); - } else { - var emphasisStyle = el.states.emphasis && el.states.emphasis.style ? el.states.emphasis.style : {}; - var fill = emphasisStyle.fill; - - if (!fill) { - var normalFill = el.style && el.style.fill; - var selectFill = el.states.select && el.states.select.style && el.states.select.style.fill; - var fromFill = el.currentStates.indexOf('select') >= 0 ? selectFill || normalFill : normalFill; - - if (fromFill) { - fill = liftColor(fromFill); - } - } - - var lineWidth = emphasisStyle.lineWidth; - - if (lineWidth) { - var scaleX = !emphasisStyle.strokeNoScale && el.transform ? el.transform[0] : 1; - lineWidth = lineWidth / scaleX; - } - - var style = { - cursor: 'pointer' - }; - - if (fill) { - style.fill = fill; - } - - if (emphasisStyle.stroke) { - style.stroke = emphasisStyle.stroke; - } - - if (lineWidth) { - style['stroke-width'] = lineWidth; - } - - setClassAttribute(style, attrs, scope, true); - } - } - } - - function setClassAttribute(style, attrs, scope, withHover) { - var styleKey = JSON.stringify(style); - var className = scope.cssStyleCache[styleKey]; - - if (!className) { - className = scope.zrId + '-cls-' + getClassId(); - scope.cssStyleCache[styleKey] = className; - scope.cssNodes['.' + className + (withHover ? ':hover' : '')] = style; - } - - attrs["class"] = attrs["class"] ? attrs["class"] + ' ' + className : className; - } - - var round = Math.round; - - function isImageLike(val) { - return val && isString(val.src); - } - - function isCanvasLike(val) { - return val && isFunction(val.toDataURL); - } - - function setStyleAttrs(attrs, style, el, scope) { - mapStyleToAttrs(function (key, val) { - var isFillStroke = key === 'fill' || key === 'stroke'; - - if (isFillStroke && isGradient(val)) { - setGradient(style, attrs, key, scope); - } else if (isFillStroke && isPattern(val)) { - setPattern(el, attrs, key, scope); - } else if (isFillStroke && val === 'none') { - attrs[key] = 'transparent'; - } else { - attrs[key] = val; - } - }, style, el, false); - setShadow(el, attrs, scope); - } - - function setMetaData(attrs, el) { - var metaData = getElementSSRData(el); - - if (metaData) { - metaData.each(function (val, key) { - val != null && (attrs[(META_DATA_PREFIX + key).toLowerCase()] = val + ''); - }); - - if (el.isSilent()) { - attrs[META_DATA_PREFIX + 'silent'] = 'true'; - } - } - } - - function noRotateScale(m) { - return isAroundZero(m[0] - 1) && isAroundZero(m[1]) && isAroundZero(m[2]) && isAroundZero(m[3] - 1); - } - - function noTranslate(m) { - return isAroundZero(m[4]) && isAroundZero(m[5]); - } - - function setTransform(attrs, m, compress) { - if (m && !(noTranslate(m) && noRotateScale(m))) { - var mul = compress ? 10 : 1e4; - attrs.transform = noRotateScale(m) ? "translate(" + round(m[4] * mul) / mul + " " + round(m[5] * mul) / mul + ")" : getMatrixStr(m); - } - } - - function convertPolyShape(shape, attrs, mul) { - var points = shape.points; - var strArr = []; - - for (var i = 0; i < points.length; i++) { - strArr.push(round(points[i][0] * mul) / mul); - strArr.push(round(points[i][1] * mul) / mul); - } - - attrs.points = strArr.join(' '); - } - - function validatePolyShape(shape) { - return !shape.smooth; - } - - function createAttrsConvert(desc) { - var normalizedDesc = map$1(desc, function (item) { - return typeof item === 'string' ? [item, item] : item; - }); - return function (shape, attrs, mul) { - for (var i = 0; i < normalizedDesc.length; i++) { - var item = normalizedDesc[i]; - var val = shape[item[0]]; - - if (val != null) { - attrs[item[1]] = round(val * mul) / mul; - } - } - }; - } - - var builtinShapesDef = { - circle: [createAttrsConvert(['cx', 'cy', 'r'])], - polyline: [convertPolyShape, validatePolyShape], - polygon: [convertPolyShape, validatePolyShape] - }; - - function hasShapeAnimation(el) { - var animators = el.animators; - - for (var i = 0; i < animators.length; i++) { - if (animators[i].targetName === 'shape') { - return true; - } - } - - return false; - } - - function brushSVGPath(el, scope) { - var style = el.style; - var shape = el.shape; - var builtinShpDef = builtinShapesDef[el.type]; - var attrs = {}; - var needsAnimate = scope.animation; - var svgElType = 'path'; - var strokePercent = el.style.strokePercent; - var precision = scope.compress && getPathPrecision(el) || 4; - - if (builtinShpDef && !scope.willUpdate && !(builtinShpDef[1] && !builtinShpDef[1](shape)) && !(needsAnimate && hasShapeAnimation(el)) && !(strokePercent < 1)) { - svgElType = el.type; - var mul = Math.pow(10, precision); - builtinShpDef[0](shape, attrs, mul); - } else { - var needBuildPath = !el.path || el.shapeChanged(); - - if (!el.path) { - el.createPathProxy(); - } - - var path = el.path; - - if (needBuildPath) { - path.beginPath(); - el.buildPath(path, el.shape); - el.pathUpdated(); - } - - var pathVersion = path.getVersion(); - var elExt = el; - var svgPathBuilder = elExt.__svgPathBuilder; - - if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || strokePercent !== elExt.__svgPathStrokePercent) { - if (!svgPathBuilder) { - svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); - } - - svgPathBuilder.reset(precision); - path.rebuildPath(svgPathBuilder, strokePercent); - svgPathBuilder.generateStr(); - elExt.__svgPathVersion = pathVersion; - elExt.__svgPathStrokePercent = strokePercent; - } - - attrs.d = svgPathBuilder.getStr(); - } - - setTransform(attrs, el.transform); - setStyleAttrs(attrs, style, el, scope); - setMetaData(attrs, el); - scope.animation && createCSSAnimation(el, attrs, scope); - scope.emphasis && createCSSEmphasis(el, attrs, scope); - return createVNode(svgElType, el.id + '', attrs); - } - - function brushSVGImage(el, scope) { - var style = el.style; - var image = style.image; - - if (image && !isString(image)) { - if (isImageLike(image)) { - image = image.src; - } else if (isCanvasLike(image)) { - image = image.toDataURL(); - } - } - - if (!image) { - return; - } - - var x = style.x || 0; - var y = style.y || 0; - var dw = style.width; - var dh = style.height; - var attrs = { - href: image, - width: dw, - height: dh - }; - - if (x) { - attrs.x = x; - } - - if (y) { - attrs.y = y; - } - - setTransform(attrs, el.transform); - setStyleAttrs(attrs, style, el, scope); - setMetaData(attrs, el); - scope.animation && createCSSAnimation(el, attrs, scope); - return createVNode('image', el.id + '', attrs); - } - - function brushSVGTSpan(el, scope) { - var style = el.style; - var text = style.text; - text != null && (text += ''); - - if (!text || isNaN(style.x) || isNaN(style.y)) { - return; - } - - var font = style.font || DEFAULT_FONT; - var x = style.x || 0; - var y = adjustTextY$1(style.y || 0, getLineHeight(font), style.textBaseline); - var textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign] || style.textAlign; - var attrs = { - 'dominant-baseline': 'central', - 'text-anchor': textAlign - }; - - if (hasSeparateFont(style)) { - var separatedFontStr = ''; - var fontStyle = style.fontStyle; - var fontSize = parseFontSize(style.fontSize); - - if (!parseFloat(fontSize)) { - return; - } - - var fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; - var fontWeight = style.fontWeight; - separatedFontStr += "font-size:" + fontSize + ";font-family:" + fontFamily + ";"; - - if (fontStyle && fontStyle !== 'normal') { - separatedFontStr += "font-style:" + fontStyle + ";"; - } - - if (fontWeight && fontWeight !== 'normal') { - separatedFontStr += "font-weight:" + fontWeight + ";"; - } - - attrs.style = separatedFontStr; - } else { - attrs.style = "font: " + font; - } - - if (text.match(/\s/)) { - attrs['xml:space'] = 'preserve'; - } - - if (x) { - attrs.x = x; - } - - if (y) { - attrs.y = y; - } - - setTransform(attrs, el.transform); - setStyleAttrs(attrs, style, el, scope); - setMetaData(attrs, el); - scope.animation && createCSSAnimation(el, attrs, scope); - return createVNode('text', el.id + '', attrs, undefined, text); - } - - function brush(el, scope) { - if (el instanceof Path) { - return brushSVGPath(el, scope); - } else if (el instanceof ZRImage) { - return brushSVGImage(el, scope); - } else if (el instanceof TSpan) { - return brushSVGTSpan(el, scope); - } - } - - function setShadow(el, attrs, scope) { - var style = el.style; - - if (hasShadow(style)) { - var shadowKey = getShadowKey(el); - var shadowCache = scope.shadowCache; - var shadowId = shadowCache[shadowKey]; - - if (!shadowId) { - var globalScale = el.getGlobalScale(); - var scaleX = globalScale[0]; - var scaleY = globalScale[1]; - - if (!scaleX || !scaleY) { - return; - } - - var offsetX = style.shadowOffsetX || 0; - var offsetY = style.shadowOffsetY || 0; - var blur_1 = style.shadowBlur; - - var _a = normalizeColor(style.shadowColor), - opacity = _a.opacity, - color = _a.color; - - var stdDx = blur_1 / 2 / scaleX; - var stdDy = blur_1 / 2 / scaleY; - var stdDeviation = stdDx + ' ' + stdDy; - shadowId = scope.zrId + '-s' + scope.shadowIdx++; - scope.defs[shadowId] = createVNode('filter', shadowId, { - 'id': shadowId, - 'x': '-100%', - 'y': '-100%', - 'width': '300%', - 'height': '300%' - }, [createVNode('feDropShadow', '', { - 'dx': offsetX / scaleX, - 'dy': offsetY / scaleY, - 'stdDeviation': stdDeviation, - 'flood-color': color, - 'flood-opacity': opacity - })]); - shadowCache[shadowKey] = shadowId; - } - - attrs.filter = getIdURL(shadowId); - } - } - - function setGradient(style, attrs, target, scope) { - var val = style[target]; - var gradientTag; - var gradientAttrs = { - 'gradientUnits': val.global ? 'userSpaceOnUse' : 'objectBoundingBox' - }; - - if (isLinearGradient(val)) { - gradientTag = 'linearGradient'; - gradientAttrs.x1 = val.x; - gradientAttrs.y1 = val.y; - gradientAttrs.x2 = val.x2; - gradientAttrs.y2 = val.y2; - } else if (isRadialGradient(val)) { - gradientTag = 'radialGradient'; - gradientAttrs.cx = retrieve2(val.x, 0.5); - gradientAttrs.cy = retrieve2(val.y, 0.5); - gradientAttrs.r = retrieve2(val.r, 0.5); - } else { - { - logError('Illegal gradient type.'); - } - return; - } - - var colors = val.colorStops; - var colorStops = []; - - for (var i = 0, len = colors.length; i < len; ++i) { - var offset = round4(colors[i].offset) * 100 + '%'; - var stopColor = colors[i].color; - - var _a = normalizeColor(stopColor), - color = _a.color, - opacity = _a.opacity; - - var stopsAttrs = { - 'offset': offset - }; - stopsAttrs['stop-color'] = color; - - if (opacity < 1) { - stopsAttrs['stop-opacity'] = opacity; - } - - colorStops.push(createVNode('stop', i + '', stopsAttrs)); - } - - var gradientVNode = createVNode(gradientTag, '', gradientAttrs, colorStops); - var gradientKey = vNodeToString(gradientVNode); - var gradientCache = scope.gradientCache; - var gradientId = gradientCache[gradientKey]; - - if (!gradientId) { - gradientId = scope.zrId + '-g' + scope.gradientIdx++; - gradientCache[gradientKey] = gradientId; - gradientAttrs.id = gradientId; - scope.defs[gradientId] = createVNode(gradientTag, gradientId, gradientAttrs, colorStops); - } - - attrs[target] = getIdURL(gradientId); - } - - function setPattern(el, attrs, target, scope) { - var val = el.style[target]; - var boundingRect = el.getBoundingRect(); - var patternAttrs = {}; - var repeat = val.repeat; - var noRepeat = repeat === 'no-repeat'; - var repeatX = repeat === 'repeat-x'; - var repeatY = repeat === 'repeat-y'; - var child; - - if (isImagePattern(val)) { - var imageWidth_1 = val.imageWidth; - var imageHeight_1 = val.imageHeight; - var imageSrc = void 0; - var patternImage = val.image; - - if (isString(patternImage)) { - imageSrc = patternImage; - } else if (isImageLike(patternImage)) { - imageSrc = patternImage.src; - } else if (isCanvasLike(patternImage)) { - imageSrc = patternImage.toDataURL(); - } - - if (typeof Image === 'undefined') { - var errMsg = 'Image width/height must been given explictly in svg-ssr renderer.'; - assert(imageWidth_1, errMsg); - assert(imageHeight_1, errMsg); - } else if (imageWidth_1 == null || imageHeight_1 == null) { - var setSizeToVNode_1 = function (vNode, img) { - if (vNode) { - var svgEl = vNode.elm; - var width = imageWidth_1 || img.width; - var height = imageHeight_1 || img.height; - - if (vNode.tag === 'pattern') { - if (repeatX) { - height = 1; - width /= boundingRect.width; - } else if (repeatY) { - width = 1; - height /= boundingRect.height; - } - } - - vNode.attrs.width = width; - vNode.attrs.height = height; - - if (svgEl) { - svgEl.setAttribute('width', width); - svgEl.setAttribute('height', height); - } - } - }; - - var createdImage = createOrUpdateImage(imageSrc, null, el, function (img) { - noRepeat || setSizeToVNode_1(patternVNode, img); - setSizeToVNode_1(child, img); - }); - - if (createdImage && createdImage.width && createdImage.height) { - imageWidth_1 = imageWidth_1 || createdImage.width; - imageHeight_1 = imageHeight_1 || createdImage.height; - } - } - - child = createVNode('image', 'img', { - href: imageSrc, - width: imageWidth_1, - height: imageHeight_1 - }); - patternAttrs.width = imageWidth_1; - patternAttrs.height = imageHeight_1; - } else if (val.svgElement) { - child = clone$3(val.svgElement); - patternAttrs.width = val.svgWidth; - patternAttrs.height = val.svgHeight; - } - - if (!child) { - return; - } - - var patternWidth; - var patternHeight; - - if (noRepeat) { - patternWidth = patternHeight = 1; - } else if (repeatX) { - patternHeight = 1; - patternWidth = patternAttrs.width / boundingRect.width; - } else if (repeatY) { - patternWidth = 1; - patternHeight = patternAttrs.height / boundingRect.height; - } else { - patternAttrs.patternUnits = 'userSpaceOnUse'; - } - - if (patternWidth != null && !isNaN(patternWidth)) { - patternAttrs.width = patternWidth; - } - - if (patternHeight != null && !isNaN(patternHeight)) { - patternAttrs.height = patternHeight; - } - - var patternTransform = getSRTTransformString(val); - patternTransform && (patternAttrs.patternTransform = patternTransform); - var patternVNode = createVNode('pattern', '', patternAttrs, [child]); - var patternKey = vNodeToString(patternVNode); - var patternCache = scope.patternCache; - var patternId = patternCache[patternKey]; - - if (!patternId) { - patternId = scope.zrId + '-p' + scope.patternIdx++; - patternCache[patternKey] = patternId; - patternAttrs.id = patternId; - patternVNode = scope.defs[patternId] = createVNode('pattern', patternId, patternAttrs, [child]); - } - - attrs[target] = getIdURL(patternId); - } - - function setClipPath(clipPath, attrs, scope) { - var clipPathCache = scope.clipPathCache, - defs = scope.defs; - var clipPathId = clipPathCache[clipPath.id]; - - if (!clipPathId) { - clipPathId = scope.zrId + '-c' + scope.clipPathIdx++; - var clipPathAttrs = { - id: clipPathId - }; - clipPathCache[clipPath.id] = clipPathId; - defs[clipPathId] = createVNode('clipPath', clipPathId, clipPathAttrs, [brushSVGPath(clipPath, scope)]); - } - - attrs['clip-path'] = getIdURL(clipPathId); - } - - function createTextNode(text) { - return document.createTextNode(text); - } - - function insertBefore(parentNode, newNode, referenceNode) { - parentNode.insertBefore(newNode, referenceNode); - } - - function removeChild(node, child) { - node.removeChild(child); - } - - function appendChild(node, child) { - node.appendChild(child); - } - - function parentNode(node) { - return node.parentNode; - } - - function nextSibling(node) { - return node.nextSibling; - } - - function setTextContent(node, text) { - node.textContent = text; - } - - var colonChar = 58; - var xChar = 120; - var emptyNode = createVNode('', ''); - - function isUndef(s) { - return s === undefined; - } - - function isDef(s) { - return s !== undefined; - } - - function createKeyToOldIdx(children, beginIdx, endIdx) { - var map = {}; - - for (var i = beginIdx; i <= endIdx; ++i) { - var key = children[i].key; - - if (key !== undefined) { - { - if (map[key] != null) { - console.error("Duplicate key " + key); - } - } - map[key] = i; - } - } - - return map; - } - - function sameVnode(vnode1, vnode2) { - var isSameKey = vnode1.key === vnode2.key; - var isSameTag = vnode1.tag === vnode2.tag; - return isSameTag && isSameKey; - } - - function createElm(vnode) { - var i; - var children = vnode.children; - var tag = vnode.tag; - - if (isDef(tag)) { - var elm = vnode.elm = createElement(tag); - updateAttrs(emptyNode, vnode); - - if (isArray(children)) { - for (i = 0; i < children.length; ++i) { - var ch = children[i]; - - if (ch != null) { - appendChild(elm, createElm(ch)); - } - } - } else if (isDef(vnode.text) && !isObject$2(vnode.text)) { - appendChild(elm, createTextNode(vnode.text)); - } - } else { - vnode.elm = createTextNode(vnode.text); - } - - return vnode.elm; - } - - function addVnodes(parentElm, before, vnodes, startIdx, endIdx) { - for (; startIdx <= endIdx; ++startIdx) { - var ch = vnodes[startIdx]; - - if (ch != null) { - insertBefore(parentElm, createElm(ch), before); - } - } - } - - function removeVnodes(parentElm, vnodes, startIdx, endIdx) { - for (; startIdx <= endIdx; ++startIdx) { - var ch = vnodes[startIdx]; - - if (ch != null) { - if (isDef(ch.tag)) { - var parent_1 = parentNode(ch.elm); - removeChild(parent_1, ch.elm); - } else { - removeChild(parentElm, ch.elm); - } - } - } - } - - function updateAttrs(oldVnode, vnode) { - var key; - var elm = vnode.elm; - var oldAttrs = oldVnode && oldVnode.attrs || {}; - var attrs = vnode.attrs || {}; - - if (oldAttrs === attrs) { - return; - } - - for (key in attrs) { - var cur = attrs[key]; - var old = oldAttrs[key]; - - if (old !== cur) { - if (cur === true) { - elm.setAttribute(key, ''); - } else if (cur === false) { - elm.removeAttribute(key); - } else { - if (key === 'style') { - elm.style.cssText = cur; - } else if (key.charCodeAt(0) !== xChar) { - elm.setAttribute(key, cur); - } else if (key === 'xmlns:xlink' || key === 'xmlns') { - elm.setAttributeNS(XMLNS, key, cur); - } else if (key.charCodeAt(3) === colonChar) { - elm.setAttributeNS(XML_NAMESPACE, key, cur); - } else if (key.charCodeAt(5) === colonChar) { - elm.setAttributeNS(XLINKNS, key, cur); - } else { - elm.setAttribute(key, cur); - } - } - } - } - - for (key in oldAttrs) { - if (!(key in attrs)) { - elm.removeAttribute(key); - } - } - } - - function updateChildren(parentElm, oldCh, newCh) { - var oldStartIdx = 0; - var newStartIdx = 0; - var oldEndIdx = oldCh.length - 1; - var oldStartVnode = oldCh[0]; - var oldEndVnode = oldCh[oldEndIdx]; - var newEndIdx = newCh.length - 1; - var newStartVnode = newCh[0]; - var newEndVnode = newCh[newEndIdx]; - var oldKeyToIdx; - var idxInOld; - var elmToMove; - var before; - - while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { - if (oldStartVnode == null) { - oldStartVnode = oldCh[++oldStartIdx]; - } else if (oldEndVnode == null) { - oldEndVnode = oldCh[--oldEndIdx]; - } else if (newStartVnode == null) { - newStartVnode = newCh[++newStartIdx]; - } else if (newEndVnode == null) { - newEndVnode = newCh[--newEndIdx]; - } else if (sameVnode(oldStartVnode, newStartVnode)) { - patchVnode(oldStartVnode, newStartVnode); - oldStartVnode = oldCh[++oldStartIdx]; - newStartVnode = newCh[++newStartIdx]; - } else if (sameVnode(oldEndVnode, newEndVnode)) { - patchVnode(oldEndVnode, newEndVnode); - oldEndVnode = oldCh[--oldEndIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (sameVnode(oldStartVnode, newEndVnode)) { - patchVnode(oldStartVnode, newEndVnode); - insertBefore(parentElm, oldStartVnode.elm, nextSibling(oldEndVnode.elm)); - oldStartVnode = oldCh[++oldStartIdx]; - newEndVnode = newCh[--newEndIdx]; - } else if (sameVnode(oldEndVnode, newStartVnode)) { - patchVnode(oldEndVnode, newStartVnode); - insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm); - oldEndVnode = oldCh[--oldEndIdx]; - newStartVnode = newCh[++newStartIdx]; - } else { - if (isUndef(oldKeyToIdx)) { - oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); - } - - idxInOld = oldKeyToIdx[newStartVnode.key]; - - if (isUndef(idxInOld)) { - insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm); - } else { - elmToMove = oldCh[idxInOld]; - - if (elmToMove.tag !== newStartVnode.tag) { - insertBefore(parentElm, createElm(newStartVnode), oldStartVnode.elm); - } else { - patchVnode(elmToMove, newStartVnode); - oldCh[idxInOld] = undefined; - insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm); - } - } - - newStartVnode = newCh[++newStartIdx]; - } - } - - if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) { - if (oldStartIdx > oldEndIdx) { - before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm; - addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx); - } else { - removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx); - } - } - } - - function patchVnode(oldVnode, vnode) { - var elm = vnode.elm = oldVnode.elm; - var oldCh = oldVnode.children; - var ch = vnode.children; - - if (oldVnode === vnode) { - return; - } - - updateAttrs(oldVnode, vnode); - - if (isUndef(vnode.text)) { - if (isDef(oldCh) && isDef(ch)) { - if (oldCh !== ch) { - updateChildren(elm, oldCh, ch); - } - } else if (isDef(ch)) { - if (isDef(oldVnode.text)) { - setTextContent(elm, ''); - } - - addVnodes(elm, null, ch, 0, ch.length - 1); - } else if (isDef(oldCh)) { - removeVnodes(elm, oldCh, 0, oldCh.length - 1); - } else if (isDef(oldVnode.text)) { - setTextContent(elm, ''); - } - } else if (oldVnode.text !== vnode.text) { - if (isDef(oldCh)) { - removeVnodes(elm, oldCh, 0, oldCh.length - 1); - } - - setTextContent(elm, vnode.text); - } - } - - function patch(oldVnode, vnode) { - if (sameVnode(oldVnode, vnode)) { - patchVnode(oldVnode, vnode); - } else { - var elm = oldVnode.elm; - var parent_2 = parentNode(elm); - createElm(vnode); - - if (parent_2 !== null) { - insertBefore(parent_2, vnode.elm, nextSibling(elm)); - removeVnodes(parent_2, [oldVnode], 0, 0); - } - } - - return vnode; - } - - var svgId = 0; - - var SVGPainter = function () { - function SVGPainter(root, storage, opts) { - this.type = 'svg'; - this.refreshHover = createMethodNotSupport('refreshHover'); - this.configLayer = createMethodNotSupport('configLayer'); - this.storage = storage; - this._opts = opts = extend({}, opts); - this.root = root; - this._id = 'zr' + svgId++; - this._oldVNode = createSVGVNode(opts.width, opts.height); - - if (root && !opts.ssr) { - var viewport = this._viewport = document.createElement('div'); - viewport.style.cssText = 'position:relative;overflow:hidden'; - var svgDom = this._svgDom = this._oldVNode.elm = createElement('svg'); - updateAttrs(null, this._oldVNode); - viewport.appendChild(svgDom); - root.appendChild(viewport); - } - - this.resize(opts.width, opts.height); - } - - SVGPainter.prototype.getType = function () { - return this.type; - }; - - SVGPainter.prototype.getViewportRoot = function () { - return this._viewport; - }; - - SVGPainter.prototype.getViewportRootOffset = function () { - var viewportRoot = this.getViewportRoot(); - - if (viewportRoot) { - return { - offsetLeft: viewportRoot.offsetLeft || 0, - offsetTop: viewportRoot.offsetTop || 0 - }; - } - }; - - SVGPainter.prototype.getSvgDom = function () { - return this._svgDom; - }; - - SVGPainter.prototype.refresh = function () { - if (this.root) { - var vnode = this.renderToVNode({ - willUpdate: true - }); - vnode.attrs.style = 'position:absolute;left:0;top:0;user-select:none'; - patch(this._oldVNode, vnode); - this._oldVNode = vnode; - } - }; - - SVGPainter.prototype.renderOneToVNode = function (el) { - return brush(el, createBrushScope(this._id)); - }; - - SVGPainter.prototype.renderToVNode = function (opts) { - opts = opts || {}; - var list = this.storage.getDisplayList(true); - var width = this._width; - var height = this._height; - var scope = createBrushScope(this._id); - scope.animation = opts.animation; - scope.willUpdate = opts.willUpdate; - scope.compress = opts.compress; - scope.emphasis = opts.emphasis; - var children = []; - var bgVNode = this._bgVNode = createBackgroundVNode(width, height, this._backgroundColor, scope); - bgVNode && children.push(bgVNode); - var mainVNode = !opts.compress ? this._mainVNode = createVNode('g', 'main', {}, []) : null; - - this._paintList(list, scope, mainVNode ? mainVNode.children : children); - - mainVNode && children.push(mainVNode); - var defs = map$1(keys(scope.defs), function (id) { - return scope.defs[id]; - }); - - if (defs.length) { - children.push(createVNode('defs', 'defs', {}, defs)); - } - - if (opts.animation) { - var animationCssStr = getCssString(scope.cssNodes, scope.cssAnims, { - newline: true - }); - - if (animationCssStr) { - var styleNode = createVNode('style', 'stl', {}, [], animationCssStr); - children.push(styleNode); - } - } - - return createSVGVNode(width, height, children, opts.useViewBox); - }; - - SVGPainter.prototype.renderToString = function (opts) { - opts = opts || {}; - return vNodeToString(this.renderToVNode({ - animation: retrieve2(opts.cssAnimation, true), - emphasis: retrieve2(opts.cssEmphasis, true), - willUpdate: false, - compress: true, - useViewBox: retrieve2(opts.useViewBox, true) - }), { - newline: true - }); - }; - - SVGPainter.prototype.setBackgroundColor = function (backgroundColor) { - this._backgroundColor = backgroundColor; - }; - - SVGPainter.prototype.getSvgRoot = function () { - return this._mainVNode && this._mainVNode.elm; - }; - - SVGPainter.prototype._paintList = function (list, scope, out) { - var listLen = list.length; - var clipPathsGroupsStack = []; - var clipPathsGroupsStackDepth = 0; - var currentClipPathGroup; - var prevClipPaths; - var clipGroupNodeIdx = 0; - - for (var i = 0; i < listLen; i++) { - var displayable = list[i]; - - if (!displayable.invisible) { - var clipPaths = displayable.__clipPaths; - var len = clipPaths && clipPaths.length || 0; - var prevLen = prevClipPaths && prevClipPaths.length || 0; - var lca = void 0; - - for (lca = Math.max(len - 1, prevLen - 1); lca >= 0; lca--) { - if (clipPaths && prevClipPaths && clipPaths[lca] === prevClipPaths[lca]) { - break; - } - } - - for (var i_1 = prevLen - 1; i_1 > lca; i_1--) { - clipPathsGroupsStackDepth--; - currentClipPathGroup = clipPathsGroupsStack[clipPathsGroupsStackDepth - 1]; - } - - for (var i_2 = lca + 1; i_2 < len; i_2++) { - var groupAttrs = {}; - setClipPath(clipPaths[i_2], groupAttrs, scope); - var g = createVNode('g', 'clip-g-' + clipGroupNodeIdx++, groupAttrs, []); - (currentClipPathGroup ? currentClipPathGroup.children : out).push(g); - clipPathsGroupsStack[clipPathsGroupsStackDepth++] = g; - currentClipPathGroup = g; - } - - prevClipPaths = clipPaths; - var ret = brush(displayable, scope); - - if (ret) { - (currentClipPathGroup ? currentClipPathGroup.children : out).push(ret); - } - } - } - }; - - SVGPainter.prototype.resize = function (width, height) { - var opts = this._opts; - var root = this.root; - var viewport = this._viewport; - width != null && (opts.width = width); - height != null && (opts.height = height); - - if (root && viewport) { - viewport.style.display = 'none'; - width = getSize(root, 0, opts); - height = getSize(root, 1, opts); - viewport.style.display = ''; - } - - if (this._width !== width || this._height !== height) { - this._width = width; - this._height = height; - - if (viewport) { - var viewportStyle = viewport.style; - viewportStyle.width = width + 'px'; - viewportStyle.height = height + 'px'; - } - - if (!isPattern(this._backgroundColor)) { - var svgDom = this._svgDom; - - if (svgDom) { - svgDom.setAttribute('width', width); - svgDom.setAttribute('height', height); - } - - var bgEl = this._bgVNode && this._bgVNode.elm; - - if (bgEl) { - bgEl.setAttribute('width', width); - bgEl.setAttribute('height', height); - } - } else { - this.refresh(); - } - } - }; - - SVGPainter.prototype.getWidth = function () { - return this._width; - }; - - SVGPainter.prototype.getHeight = function () { - return this._height; - }; - - SVGPainter.prototype.dispose = function () { - if (this.root) { - this.root.innerHTML = ''; - } - - this._svgDom = this._viewport = this.storage = this._oldVNode = this._bgVNode = this._mainVNode = null; - }; - - SVGPainter.prototype.clear = function () { - if (this._svgDom) { - this._svgDom.innerHTML = null; - } - - this._oldVNode = null; - }; - - SVGPainter.prototype.toDataURL = function (base64) { - var str = this.renderToString(); - var prefix = 'data:image/svg+xml;'; - - if (base64) { - str = encodeBase64(str); - return str && prefix + 'base64,' + str; - } - - return prefix + 'charset=UTF-8,' + encodeURIComponent(str); - }; - - return SVGPainter; - }(); - - function createMethodNotSupport(method) { - return function () { - { - logError('In SVG mode painter not support method "' + method + '"'); - } - }; - } - - function createBackgroundVNode(width, height, backgroundColor, scope) { - var bgVNode; - - if (backgroundColor && backgroundColor !== 'none') { - bgVNode = createVNode('rect', 'bg', { - width: width, - height: height, - x: '0', - y: '0' - }); - - if (isGradient(backgroundColor)) { - setGradient({ - fill: backgroundColor - }, bgVNode.attrs, 'fill', scope); - } else if (isPattern(backgroundColor)) { - setPattern({ - style: { - fill: backgroundColor - }, - dirty: noop, - getBoundingRect: function () { - return { - width: width, - height: height - }; - } - }, bgVNode.attrs, 'fill', scope); - } else { - var _a = normalizeColor(backgroundColor), - color = _a.color, - opacity = _a.opacity; - - bgVNode.attrs.fill = color; - opacity < 1 && (bgVNode.attrs['fill-opacity'] = opacity); - } - } - - return bgVNode; - } - - registerPainter('svg', SVGPainter); - exports.Axis = Axis; - exports.ChartView = ChartView; - exports.ComponentModel = ComponentModel; - exports.ComponentView = ComponentView; - exports.List = SeriesData; - exports.Model = Model; - exports.PRIORITY = PRIORITY; - exports.SeriesModel = SeriesModel; - exports.color = color; - exports.connect = connect; - exports.dataTool = dataTool; - exports.dependencies = dependencies; - exports.disConnect = disConnect; - exports.disconnect = disconnect; - exports.dispose = dispose; - exports.env = env; - exports.extendChartView = extendChartView; - exports.extendComponentModel = extendComponentModel; - exports.extendComponentView = extendComponentView; - exports.extendSeriesModel = extendSeriesModel; - exports.format = format; - exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions; - exports.getInstanceByDom = getInstanceByDom; - exports.getInstanceById = getInstanceById; - exports.getMap = getMap; - exports.graphic = graphic; - exports.helper = helper; - exports.init = init; - exports.innerDrawElementOnCanvas = brushSingle; - exports.matrix = matrix; - exports.number = number; - exports.parseGeoJSON = parseGeoJSON; - exports.parseGeoJson = parseGeoJSON; - exports.registerAction = registerAction; - exports.registerCoordinateSystem = registerCoordinateSystem; - exports.registerLayout = registerLayout; - exports.registerLoading = registerLoading; - exports.registerLocale = registerLocale; - exports.registerMap = registerMap; - exports.registerPostInit = registerPostInit; - exports.registerPostUpdate = registerPostUpdate; - exports.registerPreprocessor = registerPreprocessor; - exports.registerProcessor = registerProcessor; - exports.registerTheme = registerTheme; - exports.registerTransform = registerTransform; - exports.registerUpdateLifecycle = registerUpdateLifecycle; - exports.registerVisual = registerVisual; - exports.setCanvasCreator = setCanvasCreator; - exports.setPlatformAPI = setPlatformAPI; - exports.throttle = throttle; - exports.time = time; - exports.use = use; - exports.util = util; - exports.vector = vector; - exports.version = version; - exports.zrUtil = util$1; - exports.zrender = zrender; -}); \ No newline at end of file diff --git a/src/Qianduan/src/Ophthalmic-medication/Ophthalmic-medication.html b/src/Qianduan/src/Ophthalmic-medication/Ophthalmic-medication.html deleted file mode 100644 index cbb635f..0000000 --- a/src/Qianduan/src/Ophthalmic-medication/Ophthalmic-medication.html +++ /dev/null @@ -1,289 +0,0 @@ - - - - - - 眼科用药 - - - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Orthopedic-medication/Orthopedic-medication.html b/src/Qianduan/src/Orthopedic-medication/Orthopedic-medication.html deleted file mode 100644 index 2f229b9..0000000 --- a/src/Qianduan/src/Orthopedic-medication/Orthopedic-medication.html +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - 骨科用药 - - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Outbound-statistics/Outbound-statistics.html b/src/Qianduan/src/Outbound-statistics/Outbound-statistics.html deleted file mode 100644 index 4a50922..0000000 --- a/src/Qianduan/src/Outbound-statistics/Outbound-statistics.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - 出库药品统计 - - - - - - - -

- -

- - - - - - - - - - - - -
药名药品公司药品公司联系电话数量价格进价时间
- - - - - - \ No newline at end of file diff --git a/src/Qianduan/src/Respiratory-system-medication/Respiratory-system-medication.html b/src/Qianduan/src/Respiratory-system-medication/Respiratory-system-medication.html deleted file mode 100644 index c28d51a..0000000 --- a/src/Qianduan/src/Respiratory-system-medication/Respiratory-system-medication.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - 呼吸系统药 - - - - - - - -

- -

- - - - - - - - - - - -
药名药品公司药品公司联系电话价格库存进价
- - - - - \ No newline at end of file