<graph>
Перейти к навигации
Перейти к поиску
Описание:
Внимание! |
<graph> |
Позволяет внедрять визуализации Vega
- Автор:
- Александр Машин
width
:- ширина в пикселях
heighr
:- высота в пикселях
Визуализация
Синтаксис:<graph width="ширина в пикселях" heighr="высота в пикселях">описание на языке Vega</graph>
| ||
---|---|---|
Тематические статьи | ||
Техническая справка | ||
Тэги MediaWiki: | ||
Общие правила | ||
<graph>
— предоставляемый определённым образом настроенным расширением External data тег MediaWiki, позволяющий внедрять в страницы визуализации, отрисованные программой Vega.
Визуализация описывается особым языком, являющимся подмножеством JSON.
Особенностью реализации является то, что визуализация отрисовывается и на стороне сервера, и на стороне клиента. Первое созраняет визуализацию в средах без JavaScript, например, при экспорте в PDF, второе делает визуализации интерактивными в браузере.
Примеры[править код]
Викитекст | Вывод |
---|---|
<graph width="400">{ "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "A basic bar chart example, with value labels shown upon mouse hover.", "width": 400, "height": 200, "padding": 5, "data": [ { "name": "table", "values": [ {"category": "A", "amount": 28}, {"category": "B", "amount": 55}, {"category": "C", "amount": 43}, {"category": "D", "amount": 91}, {"category": "E", "amount": 81}, {"category": "F", "amount": 53}, {"category": "G", "amount": 19}, {"category": "H", "amount": 87} ] } ], "signals": [ { "name": "tooltip", "value": {}, "on": [ {"events": "rect:mouseover", "update": "datum"}, {"events": "rect:mouseout", "update": "{}"} ] } ], "scales": [ { "name": "xscale", "type": "band", "domain": {"data": "table", "field": "category"}, "range": "width", "padding": 0.05, "round": true }, { "name": "yscale", "domain": {"data": "table", "field": "amount"}, "nice": true, "range": "height" } ], "axes": [ { "orient": "bottom", "scale": "xscale" }, { "orient": "left", "scale": "yscale" } ], "marks": [ { "type": "rect", "from": {"data":"table"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "category"}, "width": {"scale": "xscale", "band": 1}, "y": {"scale": "yscale", "field": "amount"}, "y2": {"scale": "yscale", "value": 0} }, "update": { "fill": {"value": "steelblue"} }, "hover": { "fill": {"value": "red"} } } }, { "type": "text", "encode": { "enter": { "align": {"value": "center"}, "baseline": {"value": "bottom"}, "fill": {"value": "#333"} }, "update": { "x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5}, "y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2}, "text": {"signal": "tooltip.amount"}, "fillOpacity": [ {"test": "datum === tooltip", "value": 0}, {"value": 1} ] } } } ] }</graph> |
|
<graph width="400">{ "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "A plot of 2016 annual global precipitation data from the NOAA Climate Forecast System (CFS) v2.", "width": 600, "height": 300, "autosize": "fit-x", "signals": [ { "name": "projection", "value": "naturalEarth1", "bind": {"input": "select", "options": [ "azimuthalEqualArea", "equalEarth", "equirectangular", "naturalEarth1", "mollweide", "orthographic" ]} }, { "name": "scale", "value": 110, "bind": {"input": "range", "min": 50, "max": 400, "step": 5} }, { "name": "rotate0", "value": 0, "bind": {"input": "range", "min": -180, "max": 180, "step": 1} }, { "name": "rotate1", "value": 0, "bind": {"input": "range", "min": 0, "max": 360, "step": 1} }, { "name": "rotate2", "value": 0, "bind": {"input": "range", "min": 0, "max": 360, "step": 1} }, { "name": "opacity", "value": 0.5, "bind": {"input": "range", "min": 0, "max": 1, "step": 0.01} }, { "name": "levels", "value": 6, "bind": {"input": "range", "min": 2, "max": 12, "step": 1} }, { "name": "stop", "value": 3000 }, { "name": "step", "update": "stop / levels" } ], "data": [ { "name": "precipitation", "url": "https://vega.github.io/vega/data/annual-precip.json" }, { "name": "contours", "source": "precipitation", "transform": [ { "type": "isocontour", "thresholds": {"signal": "sequence(step, stop, step)"} } ] }, { "name": "world", "url": "https://vega.github.io/vega/data/world-110m.json", "format": {"type": "topojson", "feature": "countries"} } ], "projections": [ { "name": "projection", "type": {"signal": "projection"}, "scale": {"signal": "scale"}, "rotate": {"signal": "[rotate0, rotate1, rotate2]"}, "translate": {"signal": "[width/2, height/2]"} } ], "scales": [ { "name": "color", "type": "quantize", "domain": {"signal": "[0, stop]"}, "range": {"scheme": "bluepurple", "count": {"signal": "levels"} } } ], "marks": [ { "type": "shape", "clip": true, "from": {"data": "world"}, "encode": { "update": { "strokeWidth": {"value": 1}, "stroke": {"value": "#eee"}, "fill": {"value": "#ddd"} } }, "transform": [ { "type": "geoshape", "projection": "projection" } ] }, { "type": "shape", "clip": true, "from": { "data": "contours"}, "encode": { "update": { "fill": {"scale": "color", "field": "contour.value"}, "fillOpacity": {"signal": "opacity"} } }, "transform": [ { "type": "geoshape", "field": "datum.contour", "projection": "projection" } ] } ], "legends": [ { "title": "Annual Precipitation (mm)", "fill": "color", "orient": "bottom", "offset": 5, "type": "gradient", "gradientLength": 300, "gradientThickness": 12, "titlePadding": 10, "titleOrient": "left", "titleAnchor": "end", "direction": "horizontal" } ], "config": { "legend": {"layout": {"anchor": "middle"} } } }</graph> |
|
<graph width="400" height="350">{ "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "Interactive map of U.S. airport connections in 2008.", "width": 900, "height": 560, "padding": {"top": 25, "left": 0, "right": 0, "bottom": 0 }, "autosize": "none", "signals": [ { "name": "scale", "value": 1200, "bind": { "input": "range", "min" : 500, "max": 3000 } }, { "name": "translateX", "value": 450, "bind": { "input": "range", "min": -500, "max": 1200 } }, { "name": "translateY", "value": 260, "bind": { "input": "range", "min": -300, "max": 700 } }, { "name": "shape", "value": "line", "bind": { "input": "radio", "options": [ "line", "curve" ] } }, { "name": "hover", "value": null, "on": [ { "events": "@cell:mouseover", "update": "datum" }, { "events": "@cell:mouseout", "update": "null" } ] }, { "name": "title", "value": "U.S. Airports, 2008", "update": "hover ? hover.name + ' (' + hover.iata + ')' : 'U.S. Airports, 2008'" }, { "name": "cell_stroke", "value": null, "on": [ { "events": "dblclick", "update": "cell_stroke ? null : 'brown'"}, { "events": "mousedown!", "update": "cell_stroke" } ] } ], "data": [ { "name": "states", "url": "https://vega.github.io/vega/data/us-10m.json", "format": { "type": "topojson", "feature": "states"}, "transform": [ { "type": "geopath", "projection": "projection" } ] }, { "name": "traffic", "url": "https://vega.github.io/vega/data/flights-airport.csv", "format": {"type": "csv", "parse": "auto"}, "transform": [ { "type": "aggregate", "groupby": ["origin"], "fields": ["count"], "ops": ["sum"], "as": ["flights"] } ] }, { "name": "airports", "url": "https://vega.github.io/vega/data/airports.csv", "format": {"type": "csv","parse": "auto" }, "transform": [ { "type": "lookup", "from": "traffic", "key": "origin", "fields": ["iata"], "as": ["traffic"] }, { "type": "filter", "expr": "datum.traffic!=null" }, { "type": "geopoint", "projection": "projection", "fields": ["longitude", "latitude"] }, { "type": "filter", "expr": "!(datum.x==null || datum.y==null)" }, { "type": "voronoi", "x": "x", "y": "y" }, { "type": "collect", "sort": { "field": "traffic.flights", "order": "descending" } } ] }, { "name": "routes", "url": "https://vega.github.io/vega/data/flights-airport.csv", "format": {"type": "csv", "parse": "auto"}, "transform": [ { "type": "filter", "expr": "!(!hover || hover.iata != datum.origin)" }, { "type": "lookup", "from": "airports", "key": "iata", "fields": ["origin", "destination"], "as": ["source", "target"] }, { "type": "filter", "expr": "!(!datum.source || !datum.target)" }, { "type": "linkpath", "shape": {"signal": "shape"} } ] } ], "projections": [ { "name": "projection", "type": "albersUsa", "scale": {"signal": "scale"}, "translate": [{"signal": "translateX"}, {"signal": "translateY"}] } ], "scales": [ { "name": "size", "type": "linear", "domain": {"data": "traffic", "field": "flights"}, "range": [16, 1000] } ], "marks": [ { "type": "path", "from": {"data": "states"}, "encode": { "enter": { "fill": {"value": "#dedede"}, "stroke": {"value": "white"} }, "update": { "path": {"field": "path"} } } }, { "type": "symbol", "from": {"data": "airports"}, "encode": { "enter": { "size": {"scale": "size", "field": "traffic.flights"}, "fill": {"value": "steelblue"}, "fillOpacity": {"value": 0.8}, "stroke": {"value": "white"}, "strokeWidth": {"value": 1.5} }, "update": { "x": {"field": "x"}, "y": {"field": "y"} } } }, { "type": "path", "name": "cell", "from": {"data": "airports"}, "encode": { "enter": { "fill": {"value": "transparent"}, "strokeWidth": {"value": 0.35} }, "update": { "path": {"field": "path"}, "stroke": {"signal": "cell_stroke"} } } }, { "type": "path", "interactive": false, "from": {"data": "routes"}, "encode": { "enter": { "path": {"field": "path" }, "stroke": {"value": "black"}, "strokeOpacity": {"value": 0.35} } } }, { "type": "text", "interactive": false, "encode": { "enter": { "x": {"value": 895}, "y": {"value": 0 }, "fill": { "value": "black" }, "fontSize": { "value": 20}, "align": {"value": "right"} }, "update": { "text": {"signal": "title" } } } } ] }</graph> |
|
Требуемые настройки[править код]
// Vega
// In /var/www/js
// npm install vega-cli vega-embed vega-projection-extended
// /var/www/js/vega/config.json
/*
{
"locale": {
"number": {
"decimal": ",",
"thousands": "\u00a0",
"grouping": [3],
"currency": ["", "\u00a0₽"]
},
"time": {
"dateTime": "%A, %e %B %Y г. %X",
"date": "%d.%m.%Y",
"time": "%H:%M:%S",
"periods": ["AM", "PM"],
"days": ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
"shortDays": ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
"months": ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
"shortMonths": ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
}
}
}
*/
$edgExeName ['vega'] = 'Vega';
$edgExeUrl ['vega'] = 'https://vega.github.io';
$edgExeVersionCommand ['vega'] = '/var/www/js/node_modules/vega-cli/bin/vg2svg --version';
$edgExeCommand ['vega'] = "/var/www/js/node_modules/vega-cli/bin/vg2svg -c /var/www/js/vega/config.json -b $wgUploadDirectory";
$edgExeParams ['vega'] = ['json', 'width' => 600, 'height' => 600];
$edgExeParamFilters ['vega'] = [
'json' => function( string $json ) {
return is_array( $json ) || is_string( $json ) && json_decode( $json );
},
'width' => '/^\d+$/', 'height' => '/^\d+$/',
];
$edgExePreprocess ['vega'] = function( $json ) {
return is_array( $json ) ? json_encode( $json ) : $json;
};
$edgExePostprocess ['vega'] = static function ( $svg, array $params ) {
$json = $params['json'];
$id = hash( 'fnv1a64', $json );
if ( is_string ( $json ) ) {
// Decode JSON.
$result = \FormatJson::parse( $json, FormatJson::TRY_FIXING | FormatJson::STRIP_COMMENTS );
if ( !$result->isOK() ) {
return EDParserFunctions::formatErrorMessages( 'JSON could not be parsed' );
}
$parsed = $result->getValue();
if ( !is_object( $parsed ) ) {
return EDParserFunctions::formatErrorMessages( 'Parsed JSON is not an object' );
}
} else {
$parsed = $json;
}
// Encode JSON back.
$json = html_entity_decode( \FormatJSON::encode( $parsed, false, \FormatJSON::ALL_OK ) );
if ( $params['width'] && $params['height'] ) {
$style = "min-width:{$params['width']}; min-height:{$params['height']}";
} else {
$style ='';
}
return <<<HTML
<div class="vega" id="id_$id" style="$style">$svg</div>
HTML . "\n" . Html::inlineScript( <<<SCRIPT
(function () {
// Some bug injects & and   into json values.
const removeEntities = function ( json ) {
const nbsp = / /g;
const amp = /&/g;
if ( typeof json === 'string' || json instanceof String ) {
json = json.replace( nbsp, ' ' ).replace( amp, '&' );
} else if ( Array.isArray( json ) || typeof json === 'object' ) {
for ( key in json ) {
json[key] = removeEntities( json[key] );
}
}
return json;
}
const spec = removeEntities( $json );
var waitForJQuery = setInterval( function() {
if ( typeof $!== 'undefined' ) {
$.when(
mw.loader.getScript( '/js/node_modules/vega/build/vega.min.js' ),
mw.loader.getScript( '/js/node_modules/vega-lite/build/vega-lite.min.js' ),
mw.loader.getScript( '/js/node_modules/vega-embed/build/vega-embed.min.js' ),
).then(
function () {
vegaEmbed( '#id_$id', spec ).then( function( result ) {
console.log( 'vegaEmbed result: ' + result );
} ).catch( function( error ) {
mw.log.error( error );
});
},
function ( e ) {
// A script failed, and is not available
mw.log.error( e.message ); // => "Failed to load script"
}
);
clearInterval( waitForJQuery );
}
}, 10 );
} )();
SCRIPT );
};
$edgExeInput ['vega'] = 'json';
$edgExeTags ['vega'] = 'graph';