Arquivo da categoria: Front End

D3js v4 + Vuejs 2 – map zoom, drag points, drag map, get lon x lat

Mapa mundial com zoom scroll, move mapa, adicionar pontos no json e mover, console.log mostrando a latitude e longitude, utilizando D3.js Versão 4 escrita em ES6
Versão com Vuejs v2

HTML + CSS + JS

<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <script src="https://unpkg.com/vue"></script>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
        body {
            margin: 0;
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <div id="map"></div>
    </div>
    <script>
        const cities = [{ 'code': 'OTT', 'city': 'OTTAWA', 'country': 'CANADA', 'lat': '23.10', 'lon': '120.34' }, { 'code': 'BSB', 'city': 'BRASILIA', 'country': 'BRAZIL', 'lat': '-32.85', 'lon': '133.30' }, { 'code': 'DEL', 'city': 'DELHI', 'country': 'INDIA', 'lat': '4.71', 'lon': '-127.57' }, { 'code': 'CMX', 'city': 'CIDADE DO MÉXICO', 'country': 'MÉXICO', 'lat': '0.42', 'lon': '93.19' }, { 'code': 'SID', 'city': 'SIDNEY', 'country': 'AUSTRALIA', 'lat': '-48.38', 'lon': '-71.71' }, { 'code': 'TOK', 'city': 'TOQUIO', 'country': 'JAPÃO', 'lat': '17.34', 'lon': '-81.73' }, { 'code': 'CCA', 'city': 'CIDADE DO CABO', 'country': 'AFRICA DO SUL', 'lat': '-43.20', 'lon': '-171.97' }, { 'code': 'CMP', 'city': 'CAMPO GRANDE', 'country': 'BRASIL', 'lat': '-36.15', 'lon': '130.72' }, { 'code': 'PAR', 'city': 'PARIS', 'country': 'FRANÇA', 'lat': '22.19', 'lon': '174.27' }, { 'code': 'NOY', 'city': 'NOVA YORK', 'country': 'USA', 'lat': '11.23', 'lon': '112.96' }]

        new Vue({
            el: '#app',
            data: {
                background: 'https://upload.wikimedia.org/wikipedia/commons/8/80/World_map_-_low_resolution.svg',
                width: 960,
                height: 600,
                start_x: null,
                start_y: null,
                projection: null,
                scale: 200,
                svg: null,
                path: null,
                g: null,
                drag_handler: null
            },
            methods: {
                createMap() {
                    this.projection = d3.geoMercator()
                        .center([0, 5])
                        .scale(this.scale)
                        .rotate([-180, 0])
                    this.svg = d3.select('#map').append('svg:svg')
                        .attr('width', this.width)
                        .attr('height', this.height)
                    this.path = d3.geoPath()
                        .projection(this.projection),
                        this.g = this.svg.append('g')
                    this.g.append('image')
                        .attr('xlink:href', this.background)
                        .append('path')
                        .attr('d', this.path)

                    this.request()
                },
                request() {
                    const app = this,
                        circles = this.g.selectAll('circle')
                            .data(cities)
                            .enter()
                            .append('a')
                            .attr('xlink:href', d => `https://www.google.com/search?q=${d.city}`
                            )
                            .append('circle')
                            .attr('cx', d => this.projection([d.lon, d.lat])[0])
                            .attr('cy', d => this.projection([d.lon, d.lat])[1])
                            .attr('r', 5)
                            .style('fill', 'red')

                    this.drag_handler = d3.drag()
                        .on('start', this.drag_start)
                        .on('drag', (d, i, a) => this.drag_drag(d, i, a))

                    this.drag_handler(circles)
                },
                drag_start() {
                    this.start_x = +d3.event.x
                    this.start_y = +d3.event.y
                },
                drag_drag(d, i, a) {
                    console.log(
                        'lon x lat', this.projection.invert([d3.event.x, d3.event.y])
                    )
                    d3.select(a[i])
                        .attr('cx', d.x = d3.event.x).attr('cy', d.y = d3.event.y)
                }
            },
            mounted() {
                this.createMap()
                const zoom = d3.zoom()
                    .scaleExtent([0.1, 1]) //zoom limit
                    .on('zoom', () => {
                        this.g.style('stroke-width', `${1.5 / d3.event.transform.k}px`)
                        this.g.attr('transform', d3.event.transform) // updated for d3 v4
                    })

                this.svg.call(zoom)
                    //.call(zoom.transform, d3.zoomIdentity.translate(200, 20).scale(0.25)) //initial size
                    .append('svg:g')
                    .attr('transform', 'translate(100,50) scale(.5,.5)');
            }
        })
    </script>
</body>
</html>

Demo: https://bl.ocks.org/sistemawebpro/41d81ad70d7355691a61a6f7ac7f83d9

Loop dentro de loop utilizando o LESS


@maxi: 2;
.i-loop (@i) when (@i > 0) {

@maxj: 3;
.j-loop (@j) when (@j > 0) {

.my-class-@{i}-@{j} {
width: (100% / @i);
height: (100% / @j);
}

.j-loop(@j - 1);
}
.j-loop (0) {}
.j-loop(@maxj);

.i-loop(@i - 1);
}
.i-loop (0) {}
.i-loop(@maxi);

return:
.my-class-2-3 {
width: 50%;
height: 33.33333333%;
}
.my-class-2-2 {
width: 50%;
height: 50%;
}
.my-class-2-1 {
width: 50%;
height: 100%;
}
.my-class-1-3 {
width: 100%;
height: 33.33333333%;
}
.my-class-1-2 {
width: 100%;
height: 50%;
}
.my-class-1-1 {
width: 100%;
height: 100%;
}

JointJS – Biblioteca para criação de diagramas JS

jointjs

Surgiu-se a necessidade de criação de diagramas, fui a pesquisa para encontrar alguma ferramenta para auxiliar, como existe vários prontos não é necessário criar a roda.

Encontrei diversos plugins mas nenhum havia me chamado atenção, uma que gostei muito foi o D3.js mas achei muito complicado sui manipulação, muito trabalhoso pra criar exatamente o que queria.

Das que encontrei, me chamaram muito atenção esses plugin:
GoJS – Infelizmente é paga
img_551d33df0354a

JsPlumb – Grátis
img_551d34ebec5c3

mermaid – Grátis
header

A que mais gostei foi JointJS com esse plugin é possível criar diagramas interessante, de um forma simples e poderosa.

A instalação super simples, necessário:

<link rel="stylesheet" type="text/css" href="joint.css" />
<script src="jquery.min.js"></script>
<script src="lodash.min.js"></script>
<script src="backbone-min.js"></script>
<script src="joint.js"></script>

jQuery: 2.0.3
Lodash: 3.10.1
Backbone: 1.2.1

Development version (0.9.5)
joint.js joint.css

Production version (0.9.5)
joint.min.js joint.min.css

Algumas imagens das possibilidades do JointJS.
ivr

traceroutes

rappid-new-showcase

rappid_attack_designer

Introdução ao Kendo UI Core

Estou inicializando a utilização do Kendo UI Core em novos projetos, então eu pensei em documentar o processo que eu uso para obter Kendo UI Core instalado e funcionando.

Passo 1) Baixar
Estarei utilizando o Bower, Gerenciador de pacotes para aplicações web:

$ bower install kendo-ui-core

Você pode baixar por alternativa Kendo UI Core pelo GitHub

Passo 2) HTML
Em seguida vamos criar um index.html e colar o seguinte código HTML:

<!doctype html>
<html lang="pt-BR">
<head>
    <meta charset="utf-8">
    <title>Meu Projeto</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="bower_components/kendo-ui-core/src/styles/web/kendo.common.core.css">
    <link rel="stylesheet" href="bower_components/kendo-ui-core/src/styles/web/kendo.flat.css">
</head>
<body>

<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/kendo-ui-core/src/js/kendo.ui.core.js"></script>

</body>
</html>

Etapa 3) Gerenciamento de Pacotes
Vou utilizar a biblioteca RequireJS para gerenciar as dependências do meu aplicativo, e como felizmente Kendo UI Core é inteligentemente dividido em módulos fica mais fácil essa utilização. Para começar vamos baixar RequireJS o que irá manipular quais scripts serão carregados na página que estarei trabalhando vamos utilizar o Bower:

$ bower install requirejs

Em seguida vou criar um arquivo app.js para servir como o principal arquivo JavaScript para meu aplicativo. Neste ponto estrutura de pastas do meu projeto será desta forma:

.
├── bower_components
│   ├── jquery
│   │   └── ...
│   ├── kendo-ui-core
│   │   └── ...
│   └── requirejs
│       └── ...
├── index.html
└── js
    └── app.js

Com esta estrutura vou incluir na minha index.html esta única tag

<script>

:

<script src="bower_components/requirejs/require.js" data-main="js/app"></script>

Em “app.js” vou incluir o seguinte código:

require.config({
    paths: {
        "jquery": "/bower_components/jquery/dist/jquery",
        "kendo-ui-core": "/bower_components/kendo-ui-core/src/js"
    }
});

require([ "jquery", "kendo-ui-core/kendo.ui.core" ], function( $ ) {

});

Isso me dá um ponto de entrada para o meu app que carrega jQuery UI e Kendo Core dinamicamente. Se meu aplicativo precisa apenas de uma uma parte do Kendo UI Core eu só vou especificar os módulos que eu preciso na chamada

require()

. Evitando a chamada total de scripts a não ser utilizando dando uma melhor performance.