Posso converter texto SVG em caminho, mas reutilizar glifos?

14

Eu tenho um SVG com uma carga de texto nele. É um mapa de estacionamento com números de espaço escritos. Eu exibo isso em um navegador da Web e, graças a um maravilhoso bug no Firefox , o navegador renderiza o texto incorretamente. Vaia.

Então eu converti o texto em caminhos. Estamos falando de até 4000 rótulos separados. Talvez 15.000 novas formas agora sejam vetores. São 4MB. Normalmente você pode argumentar que isso se presta à compactação, mas eu tenho que alinhar esse SVG no HTML . Estou adicionando alterações de CSS dinamicamente e essa é a única maneira de ter suporte para vários navegadores. De qualquer maneira, a produção bruta - mesmo vasculhada - disso é muito grande para ser útil.

O que me impressiona aqui é que todos esses números de espaço compartilham glifos comuns. Zero a nove. Por que estou incluindo uma definição de forma para cada instância de cada número? Posso desduplicar estes?

Estou usando o Inkscape, mas estou aberto a sugestões.

Oli
fonte
Alguma chance de você compartilhar o arquivo SVG para que possamos experimentá-lo?
JohnB
1
Qual é o bug exatamente (captura de tela) e como você o exporta e carrega em um navegador? Há uma boa chance de que você possa corrigi-lo com apenas um estilo CSS ou um pequeno script na página para corrigir / substituir os elementos de texto. Se essa é uma exibição dinâmica de mapa, convém transformá-la em um mapa real - a maioria das bibliotecas de mapeamento de navegador (e muitas baseadas em dados) tem um ótimo suporte para rotulagem.
Brichins
1
Desculpe, o SVG não é meu para compartilhar (pertence a um cliente), mas o bug é conhecido . Essencialmente, significa que as fontes no SVG não vão diminuir o tamanho de um ponto ... O que é um problema sério se você ampliar o zoom em um mapa com milhares de vagas de estacionamento numeradas. Eles devem ter (por exemplo) ~ 0,08pt e, na verdade, são 13pt.
Oli
1
Você tem o número de bug errado, na verdade você está procurando por este
Robert Longson 2/16/16
Você pode testar isso em um subconjunto, mas pode path|simplifyajudá-lo? Um "s" minúsculo se converte em um caminho de 28 pontos, simplifica o aumento para 17 e, sobrepondo as versões simplificadas e não simplificadas até com zoom, para que um "s" preencha a tela, não há diferença.
Chris H

Respostas:

6

O <use>elemento permite reutilizar objetos definidos em outras partes do documento. Por exemplo, você pode definir cada glifo como a <symbol>e reutilizá-los várias vezes. Aqui está um artigo agradável sobre ele: Estruturação, Agrupamento, e referenciando em SVG - A <g>, <use>, <defs>e <symbol>Elements .

Porém, não sei como fazer isso diretamente no Inkscape - especialmente para um monte de texto que você já possui como texto. Pode ser necessário escrever um script para pós-processar o SVG e encontrar todos os caminhos que podem ser reutilizados.

Rahul
fonte
A <use>era o que eu estava pensando quando eu perguntei isso, o script é o como. Parece bobagem que não haja nada lá para duplicar marcações quase idênticas.
Oli
@ Ali não havia nada para deduzir a marcação idêntica ; Eu tinha que escrever a minha própria (e por que quero dizer idêntico ao byte; I hash-los e hashes comparação)
Chris H
Pensei durante o almoço e me parece que um script (python) dentro do inkscape seria o caminho a seguir. O script seria começar com o texto como texto, e substituí-lo com referências à <symbol>s (ou parece que você poderia <def>seus glifos de texto-para-path
Chris H
4

Existem algumas opções de compactação disponíveis que oferecem graus variados de sucesso. Para testá-los, criei um arquivo de arte que tinha apenas muito texto repetido. Sem expansão, o tamanho do arquivo é 13,8 KB. Expandido, o tamanho do arquivo é 1,42 MB .

Boa opção: Use SVGZ - 46,5 KB

Salvar o trabalho artístico expandido como SVGZ me deu um arquivo de saída de 46,5 KB, que é significativamente menor que o SVG padrão. Observe que esse suporte pode variar .

Melhor opção: Comprima com Scour - 21.1 KB

O Scour é uma ferramenta que limpa e otimiza seu arquivo SVG para você. Usando o comando "compressão máxima" de scour -i input.svg -o output.svgz --enable-viewboxing --enable-id-stripping --enable-comment-stripping --shorten-ids --indent=none, o trabalho artístico expandido foi reduzido para 21,1 KB. Não muito longe do tamanho original do arquivo não expandido!

JohnB
fonte
3
A limpeza não é compactada, apenas remove o lixo e, embora faça uma boa quantidade de coisas boas para mim (dado o grande número de objetos), meus "4MB" foram pós-limpeza. O conteúdo compactado seria ótimo, mas - e eu deveria ter mencionado isso antes - tenho que alinhar o SVG para problemas de segmentação de navegador (e também requisitos de manipulação de front-end). Eu sei, eu sei, é doloroso, mas confie em mim quando digo que está me machucando mais no momento. D:
Oli
Eu deveria ter dito, a parte de limpeza scournão se comprime. Ele também pode enviar o arquivo através do gzip para você, mas o material de minificação de ID e espaço em branco é o seu show principal.
Oli
@ Oli certo, daí a minha escolha cuidadosa da palavra "otimizar" :) Isso é uma chatice que o seu arquivo já esteja vasculhado ... ack!
JohnB
Eu brinquei um pouco no Illustrator; sua saída SVG respeita os símbolos. Aqui está um exemplo rápido . Seria necessário um pouco de esforço, mas você poderá criar um script do Illustrator que dividirá seu texto em caracteres individuais e os substituirá por Símbolos. O maior obstáculo que vejo seria lidar com a rotação. Se todo o texto é paralelo ao eixo X, não parece difícil, mas lidar com o texto em um ângulo pode ser um desafio. Claro, tudo o que não é muito útil se você não tem Illustrator disponível
JohnB
3

Esta é uma solução no navegador ou no servidor

Existem muitas maneiras diferentes de otimizar arquivos SVG. Parece que você já fez um pouco disso.

Alguns recursos que eu achei muito úteis são um artigo de CSS-Tricks que se concentra em detalhes muito específicos. E, especificamente, a ferramenta que usa SVGO .

Se você tiver muitos caminhos repetidos, consideraria usar o javascript para criar as formas dinamicamente. Há um exemplo aqui . Uma direção seria ter uma função definida para cada glifo e simplesmente ter cada caminho dentro do elemento svg criado por uma solicitação para essa função. Ou pegue uma string completa e / ou array de argumentos para criar seu svg embutido. Obviamente, isso espera que seus caminhos sejam maiores que o comprimento do código necessário para solicitar a referida função (suposição bastante fácil).

Lucas
fonte
1
Embora esta resposta apresente várias soluções possíveis, o SVGO parece mais interessante. Também pode ser executado no arquivo .svg para otimizá-lo. No entanto, atualmente não parece haver deduplicação de caminho. Se o solicitante acabar criando scripts personalizados de qualquer maneira, fazê-lo como um aprimoramento para o SVGO pode ser uma boa idéia.
jpa
A desduplicação @jpa antes (ou enquanto) da conversão para caminhos seria o caminho a percorrer, com certeza. Substituir todos os casos de carvão animal texto "1" com <use xlink:href="#digit_one">em que digit_oneé um caminho
Chris H
@ Chrish Não vejo por que não se pode deduzir depois também. Apenas normalize todos os caminhos para a origem no ponto de partida, use hash, use isso para descobrir se o caminho já ocorreu. Claro, não tão elegante, mas deve funcionar e pode ser mais fácil de implementar do que ter que reimplementar / descobrir toda a lógica do layout de texto.
jpa
@ jpa você poderia, mas se a normalização da origem apresentasse erros de arredondamento, o hash não corresponderia. O script no qual estou pensando chamaria o texto para o caminho do inkscape para definir os caminhos dos caracteres, mas depois os substituiria por referências a um conjunto de mestres.
Chris H
@jpa e os erros de arredondamento são reais. Em um exemplo de brinquedo da primeira curva quadrática de um diferente de zero por um no sexto lugar decimal - suficiente para estragar hash
Chris H
2

Aqui, em um nível muito alto, está o que seu script deve fazer. Sinta-se livre para usar seu idioma e ambiente preferidos, este é apenas um ponto de partida para uma lógica que deve fornecer o que você está procurando.

  • Percorra todos os elementos de texto no xml do SVG e, para os que possuem texto numérico (os lugares de estacionamento, você não especifica se há mais texto no seu svg), altere o ID criado automaticamente pelo Inkscape para uma string com esse estacionamento número do ponto. O Inkscape precisa apenas de IDs exclusivos, gera IDs não descritivos, mas respeitará e não mudará os IDs criados por outro software ou criados ou alterados manualmente pelo usuário.
  • Em uma tabela, armazene as coordenadas x e y do elemento de texto de cada vaga de estacionamento.
  • Seja no Inkscape ou por script, converta todo o texto da vaga de estacionamento em caminhos.
  • Para os dígitos de 0 a 9, acrescente ao arquivo SVG uma <defs>seção apropriada que define as informações do caminho para cada dígito.
  • Passe por todos os <g>pontos de estacionamento e substitua-os por um<use xlink:href="#digit" x=x y=y />
  • Lucro

Eu posso prever algumas complicações com as quais você terá que lidar e boa sorte com elas.

  • O loop precisará dividir a sequência de vagas de estacionamento com 2 dígitos ou mais e o espaçamento apropriado entre o primeiro dígito e os dígitos subsequentes pode ser complicado; isso vai depender muito das fontes que você está usando.
  • Você não especifica em que orientação os pontos de estacionamento estão ou se estão em configurações curvas. Devido às compensações manuais x, y para números de 2 dígitos ou mais, talvez você precise de lógica adicional para descobrir a 'orientação' de uma vaga de estacionamento e como espaçar corretamente os diferentes caminhos de dígitos individuais a partir do primeiro.

Espero que isto ajude. Boa sorte.

botwhytho
fonte