-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1711 from EnsembleUI/chartJSAgain0x45
refactor chartJS implementation for web and native to implement `onTap`
- Loading branch information
Showing
7 changed files
with
222 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
class ChartUtils { | ||
static String getClickEventScript(String chartId, {bool isWeb = false}) { | ||
// For web, we use the chart variable name pattern | ||
final chartReference = isWeb ? 'myChart$chartId' : 'window.chart'; | ||
|
||
String messageHandler = isWeb | ||
? 'window.handleMessage(\'$chartId\', JSON.stringify(dataCollection));' | ||
: 'messageHandler.postMessage(JSON.stringify(dataCollection));'; | ||
|
||
return ''' | ||
try { | ||
var activePoints = $chartReference.getElementsAtEventForMode(event, 'nearest', { intersect: true }, true); | ||
if (activePoints.length > 0) { | ||
var firstPoint = activePoints[0]; | ||
var datasetIndex = firstPoint.datasetIndex; | ||
var index = firstPoint.index; | ||
var dataset = $chartReference.data.datasets[datasetIndex] || {}; | ||
var dataCollection = { | ||
data: { | ||
label: $chartReference.data.labels[index] || '', | ||
value: dataset.data ? dataset.data[index] : '', | ||
datasetLabel: dataset.label || '', | ||
datasetIndex: datasetIndex, | ||
index: index, | ||
backgroundColor: dataset.backgroundColor || '', | ||
borderColor: dataset.borderColor || '', | ||
x: firstPoint.element.x || 0, | ||
y: firstPoint.element.y || 0, | ||
chartType: $chartReference.config.type || '', | ||
options: JSON.parse(JSON.stringify($chartReference.options, | ||
function(key, value) { | ||
return (typeof value === 'function') ? value.toString() : value; | ||
} | ||
)) || {} | ||
} | ||
}; | ||
$messageHandler | ||
} | ||
} catch (error) { | ||
console.error('Chart click handling error:', error); | ||
${isWeb | ||
? 'window.handleMessage(\'' + chartId + '\', JSON.stringify({error: error.message}));' | ||
: 'messageHandler.postMessage(JSON.stringify({error: error.message}));' | ||
} | ||
} | ||
'''; | ||
} | ||
|
||
static String getBaseHtml(String chartId, String config) { | ||
return ''' | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | ||
<style> | ||
html, body { margin: 0; padding: 0; width: 100%; height: 100%; } | ||
canvas { width: 100% !important; height: 100% !important; } | ||
</style> | ||
</head> | ||
<body> | ||
<canvas id="$chartId"></canvas> | ||
<script> | ||
try { | ||
window.chart = new Chart(document.getElementById("$chartId"), $config); | ||
document.getElementById("$chartId").onclick = function(event) { | ||
${getClickEventScript(chartId)} | ||
}; | ||
} catch (error) { | ||
console.error('Chart initialization error:', error); | ||
messageHandler.postMessage(JSON.stringify({error: error.message})); | ||
} | ||
</script> | ||
</body> | ||
</html> | ||
'''; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
modules/ensemble/lib/widget/visualization/chart_js/chart_js_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
library chart_js_state; | ||
|
||
export 'native/unsupported_chart_js_state.dart' | ||
if (dart.library.html) 'web/chart_js_state.dart' | ||
if (dart.library.io) 'native/chart_js_state.dart'; |
49 changes: 49 additions & 0 deletions
49
modules/ensemble/lib/widget/visualization/chart_js/native/chart_js_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import 'package:ensemble/util/chart_utils.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:webview_flutter/webview_flutter.dart'; | ||
import '../chart_js.dart'; | ||
|
||
class ChartJsState extends ChartJsStateBase { | ||
late WebViewController _controller; | ||
|
||
@override | ||
void evalScript(String script) { | ||
_controller.runJavaScript(''' | ||
try { | ||
if (typeof window.chart !== "undefined") { | ||
${script.replaceAll(widget.controller.chartVar, "window.chart")} | ||
} else { | ||
console.error('Chart is not initialized'); | ||
messageHandler.postMessage(JSON.stringify({error: 'Chart is not initialized'})); | ||
} | ||
} catch (error) { | ||
console.error('Script execution error:', error); | ||
messageHandler.postMessage(JSON.stringify({error: error.message})); | ||
} | ||
'''); | ||
} | ||
|
||
@override | ||
Widget buildWidget(BuildContext context) { | ||
if (widget.controller.config == '') return const Text(""); | ||
|
||
_controller = WebViewController() | ||
..setBackgroundColor(Colors.transparent) | ||
..setJavaScriptMode(JavaScriptMode.unrestricted) | ||
..addJavaScriptChannel( | ||
'messageHandler', | ||
onMessageReceived: (JavaScriptMessage message) => | ||
handleChartClick(message.message), | ||
) | ||
..loadHtmlString(ChartUtils.getBaseHtml( | ||
widget.controller.chartId, | ||
widget.controller.config, | ||
)); | ||
|
||
return SizedBox( | ||
width: widget.controller.width.toDouble(), | ||
height: widget.controller.height.toDouble(), | ||
child: WebViewWidget(controller: _controller), | ||
); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
modules/ensemble/lib/widget/visualization/chart_js/native/unsupported_chart_js_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import 'package:flutter/material.dart'; | ||
import '../chart_js.dart'; | ||
|
||
class ChartJsState extends ChartJsStateBase { | ||
@override | ||
Widget buildWidget(BuildContext context) { | ||
return const Text("ChartJs is not supported on this platform"); | ||
} | ||
|
||
@override | ||
void evalScript(String script) {} | ||
} |
44 changes: 44 additions & 0 deletions
44
modules/ensemble/lib/widget/visualization/chart_js/web/chart_js_state.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import 'package:ensemble/util/chart_utils.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:js_widget/js_widget.dart'; | ||
import '../chart_js.dart'; | ||
|
||
class ChartJsState extends ChartJsStateBase { | ||
JsWidget? jsWidget; | ||
|
||
void evalScript(String script) { | ||
if (jsWidget == null) { | ||
print('evalScript is being called on a jsWidget which is null'); | ||
} else { | ||
jsWidget!.evalScript(script); | ||
} | ||
} | ||
|
||
@override | ||
Widget buildWidget(BuildContext context) { | ||
if (widget.controller.config == '') { | ||
return const Text(""); | ||
} | ||
|
||
jsWidget = JsWidget( | ||
id: widget.controller.id!, | ||
createHtmlTag: () => | ||
'<div id="${widget.controller.chartDiv}"><canvas id="${widget.controller.chartId}"></canvas></div>', | ||
scriptToInstantiate: (String c) => ''' | ||
if (typeof ${widget.controller.chartVar} !== "undefined") ${widget.controller.chartVar}.destroy(); | ||
${widget.controller.chartVar} = new Chart(document.getElementById("${widget.controller.chartId}"), $c); | ||
${widget.controller.chartVar}.update(); | ||
document.getElementById("${widget.controller.chartId}").onclick = function(event) { | ||
${ChartUtils.getClickEventScript(widget.controller.id!, isWeb: true)} | ||
}; | ||
''', | ||
size: Size(widget.controller.width.toDouble(), | ||
widget.controller.height.toDouble()), | ||
data: widget.controller.config, | ||
scripts: const ["https://cdn.jsdelivr.net/npm/chart.js"], | ||
listener: handleChartClick, | ||
); | ||
return jsWidget!; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters