Skip to content

Commit

Permalink
Merge pull request #593 from vizzuhq/expose_data_points
Browse files Browse the repository at this point in the history
Add marker top position to draw event
  • Loading branch information
schaumb authored Oct 24, 2024
2 parents 9550dd3 + 3182d97 commit e46e2e3
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 35 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

- Changed MarkerId to be a string instead of a number.

### Added

- Add marker top and center position to draw event

## [0.14.0] - 2024-10-03

Expand Down
8 changes: 8 additions & 0 deletions src/apps/weblib/ts-api/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,19 @@ export interface Logo extends Element {
export interface Area extends Element {
tagName: 'plot-area'
}

/** Marker element position structure helper for tooltip */
export interface MarkerPosition {
top: Point
center: Point
}

/** Plot marker element of the chart representing a data point. */
export interface Marker extends Element {
tagName: 'plot-marker'
categories: Data.Record
values: Data.Record
position: MarkerPosition
/** Unique index of the marker. */
index: string
}
Expand Down
37 changes: 26 additions & 11 deletions src/chart/main/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,23 @@ class Events
struct Marker : Element
{
const Gen::Marker ▮
struct DataPosition
{
Geom::Point top;
Geom::Point center;
} position;

explicit Marker(const Gen::Marker &marker) :
explicit Marker(const Gen::Marker &marker,
const DataPosition &position) :
Element("plot-marker"),
marker(marker)
marker(marker),
position(position)
{}

void appendToJSON(Conv::JSONObj &&jsonObj) const override
{
Element::appendToJSON(
marker.appendToJSON(std::move(jsonObj)));
Element::appendToJSON(marker.appendToJSON(
std::move(jsonObj))("position", position));
}
};

Expand All @@ -268,8 +275,10 @@ class Events
{
bool horizontal;

MarkerGuide(const Gen::Marker &marker, bool horizontal) :
MarkerChild("guide", marker),
MarkerGuide(const Gen::Marker &marker,
const Marker::DataPosition &position,
bool horizontal) :
MarkerChild("guide", marker, position),
horizontal(horizontal)
{}

Expand Down Expand Up @@ -313,15 +322,19 @@ class Events
return std::make_unique<Legend>(properties);
}

static auto marker(const Gen::Marker &marker)
static auto marker(const Gen::Marker &marker,
const Marker::DataPosition &position)
{
return std::make_unique<Marker>(marker);
return std::make_unique<Marker>(marker, position);
}

static auto markerGuide(const Gen::Marker &marker,
const Marker::DataPosition &position,
bool horizontal)
{
return std::make_unique<MarkerGuide>(marker, horizontal);
return std::make_unique<MarkerGuide>(marker,
position,
horizontal);
}

static auto root()
Expand Down Expand Up @@ -362,11 +375,13 @@ class Events
}

static auto markerLabel(const std::string &label,
const Gen::Marker &marker)
const Gen::Marker &marker,
const Marker::DataPosition &position)
{
return std::make_unique<Text<MarkerChild>>(label,
"label",
marker);
marker,
position);
}

static auto dimLegendLabel(
Expand Down
15 changes: 11 additions & 4 deletions src/chart/rendering/markerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ void MarkerRenderer::drawLines(Gfx::ICanvas &canvas,
const Geom::Line line(axisPoint, blended.center);

auto guideElement =
Events::Targets::markerGuide(blended.marker, false);
Events::Targets::markerGuide(blended.marker,
blended.dataPosition,
false);

if (rootEvents.draw.plot.marker.guide->invoke(
Events::OnLineDrawEvent(*guideElement,
Expand All @@ -88,7 +90,9 @@ void MarkerRenderer::drawLines(Gfx::ICanvas &canvas,
const Geom::Line line(center, axisPoint);

auto guideElement =
Events::Targets::markerGuide(blended.marker, true);
Events::Targets::markerGuide(blended.marker,
blended.dataPosition,
true);

if (rootEvents.draw.plot.marker.guide->invoke(
Events::OnLineDrawEvent(*guideElement,
Expand Down Expand Up @@ -262,7 +266,8 @@ void MarkerRenderer::draw(Gfx::ICanvas &canvas,
canvas.setLineWidth(*rootStyle.plot.marker.borderWidth);

auto markerElement =
Events::Targets::marker(abstractMarker.marker);
Events::Targets::marker(abstractMarker.marker,
abstractMarker.dataPosition);

auto colorAlpha =
Math::FuzzyBool::And<double>(abstractMarker.enabled, factor);
Expand Down Expand Up @@ -363,7 +368,9 @@ void MarkerRenderer::drawLabel(Gfx::ICanvas &canvas,
Gfx::ColorTransform::OverrideColor(
(*labelStyle.filter)(color)*colorAlpha),
*rootEvents.draw.plot.marker.label,
Events::Targets::markerLabel(text, marker));
Events::Targets::markerLabel(text,
marker,
abstractMarker.dataPosition));
}

std::string MarkerRenderer::getLabelText(
Expand Down
12 changes: 12 additions & 0 deletions src/chart/rendering/markers/abstractmarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ AbstractMarker AbstractMarker::create(const DrawingContext &ctx,
switch (shapeType) {
case Gen::ShapeType::rectangle:
return RectangleMarker(marker,
ctx.coordSys,
ctx.getOptions(),
ctx.rootStyle);
case Gen::ShapeType::circle:
Expand Down Expand Up @@ -132,6 +133,17 @@ AbstractMarker AbstractMarker::createInterpolated(
return aMarker;
}

void AbstractMarker::setDataPosition(const CoordinateSystem &coordSys)
{
dataPosition = {
this->getLabelPos(Styles::MarkerLabel::Position::top,
coordSys)
.end,
this->getLabelPos(Styles::MarkerLabel::Position::center,
coordSys)
.begin};
}

Geom::Rect AbstractMarker::getBoundary() const
{
return Geom::Rect::Boundary(points);
Expand Down
3 changes: 3 additions & 0 deletions src/chart/rendering/markers/abstractmarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class AbstractMarker
Geom::Point center;
Geom::Rect dataRect;
double radius{};
Events::Targets::Marker::DataPosition dataPosition;

[[nodiscard]] Geom::Rect getBoundary() const;
[[nodiscard]] Geom::Line getLine() const;
Expand All @@ -51,6 +52,8 @@ class AbstractMarker
const Gen::Marker &marker,
const Gen::ShapeType &shapeType,
::Anim::InterpolateIndex lineIndex);

void setDataPosition(const CoordinateSystem &coordSys);
};

class SingleDrawMarker : public AbstractMarker
Expand Down
2 changes: 2 additions & 0 deletions src/chart/rendering/markers/circlemarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ CircleMarker::CircleMarker(const Gen::Marker &marker,
dataRect.pos = pos;
dataRect.size = Geom::Size();
radius = fabs(coordSys.verConvert(r));

setDataPosition(coordSys);
}

}
2 changes: 2 additions & 0 deletions src/chart/rendering/markers/connectingmarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ ConnectingMarker::ConnectingMarker(const DrawingContext &ctx,

dataRect.pos = isLine ? points[2] : points[1];
dataRect.size = Geom::Size{points[2] - dataRect.pos};

setDataPosition(ctx.coordSys);
}

const Gen::Marker *ConnectingMarker::getPrev(
Expand Down
3 changes: 3 additions & 0 deletions src/chart/rendering/markers/rectanglemarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Vizzu::Draw
{

RectangleMarker::RectangleMarker(const Gen::Marker &marker,
const CoordinateSystem &coordSys,
const Gen::Options &options,
const Styles::Chart &style) :
SingleDrawMarker(marker, options, Gen::ShapeType::rectangle)
Expand Down Expand Up @@ -83,6 +84,8 @@ RectangleMarker::RectangleMarker(const Gen::Marker &marker,
dataRect.pos = points[0];
dataRect.size = Geom::Size{points[2] - points[0]};
radius = 0;

setDataPosition(coordSys);
}

}
1 change: 1 addition & 0 deletions src/chart/rendering/markers/rectanglemarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class RectangleMarker : public SingleDrawMarker
{
public:
RectangleMarker(const Gen::Marker &marker,
const CoordinateSystem &coordSys,
const Gen::Options &options,
const Styles::Chart &style);
};
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/tests/features.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"refs": ["ba17dad"]
},
"events/drawing_events": {
"refs": ["33e0e4d"]
"refs": ["c3169b0"]
},
"subtitle_caption": {
"refs": ["f6dabf0"]
Expand Down
51 changes: 32 additions & 19 deletions test/e2e/tests/features/events/drawing_events.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ let isErrorLogged = false
function overlay(e, chart) {
const coordSystem = chart.feature.coordSystem
const ctx = e.renderingContext
if (e.target && e.target.position) {
const top = e.target.position.top
ctx.save()
ctx.fillStyle = '#FF00FFA0'
ctx.moveTo(top.x, top.y)
ctx.arc(top.x, top.y, 2, 0, 2 * Math.PI)
ctx.fill()
ctx.restore()
const center = e.target.position.center
ctx.save()
ctx.fillStyle = '#000000F0'
ctx.moveTo(center.x, center.y)
ctx.arc(center.x, center.y, 2, 0, 2 * Math.PI)
ctx.fill()
ctx.restore()
}
ctx.save()
ctx.fillStyle = '#FF00000F'
ctx.strokeStyle = '#FF0000A0'
Expand Down Expand Up @@ -108,14 +124,14 @@ function setupEvents(chart) {
})
})
chart.on('draw-complete', (e) => {
const reference = -476544255
const references = [329751708, -2021415194]
receivedEvents.push(e)
const result = JSON.stringify(receivedEvents, null, 2)
const hash = (str) =>
str.split('').reduce((prev, curr) => (Math.imul(31, prev) + curr.charCodeAt(0)) | 0, 0)
if (hash(result) !== reference) {
if (!references.includes(hash(result))) {
if (!isErrorLogged) {
console.log('Expected hash: ' + reference)
console.log('Expected hashes: ' + references.join(' or '))
console.log('Actual hash: ' + hash(result))
isErrorLogged = true
}
Expand All @@ -139,22 +155,19 @@ const data = {
const testSteps = [
(chart) => {
setupEvents(chart)
return chart.animate(
{
data,
config: {
color: 'Foo',
x: { set: 'Foo', guides: true, ticks: true, axis: true },
y: { set: 'Bar', guides: true, ticks: true, axis: true },
size: 'Baz',
label: 'Baz',
title: 'My Chart',
legend: 'size',
geometry: 'circle'
}
},
0
)
return chart.animate({
data,
config: {
color: 'Foo',
x: { set: 'Foo', guides: true, ticks: true, axis: true },
y: { set: 'Bar', guides: true, ticks: true, axis: true },
size: 'Baz',
label: 'Baz',
title: 'My Chart',
legend: 'size',
geometry: 'circle'
}
})
}
]

Expand Down

0 comments on commit e46e2e3

Please sign in to comment.