I created a collectionView inside the tableView and I took the data in JSON. In each tableview cell there are arrays for collectionviewcell which vary in number but the same collectionviewcell appears.
Here is my code:
Class ViewController.swift
import UIKit
struct ModelPurchaseRequest {
var year: String
var type: String
var listFlowStatus: [String]
var listFlowPosition: [String]
init(year: String, type: String, listFlowStatus: [String], listFlowPosition: [String]) {
self.year = year
self.type = type
self.listFlowStatus = listFlowStatus
self.listFlowPosition = listFlowPosition
}
}
var listFlowStatus = [String]()
var listFlagPosition = [String]()
var modelPurchase = [ModelPurchaseRequest]()
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var flowStatus = ""
var flagPosition = ""
var purYear = ""
var purType = ""
override func viewDidLoad() {
super.viewDidLoad()
getDataPurchaseRequest()
}
func getDataPurchaseRequest() {
let url = URL(string: "https://xxxxxxxxxxxxxx")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print("Get list purchase request error")
return
}
print(response!)
guard data != nil else {return}
do {
modelPurchase.removeAll()
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: Any]
print(json)
let statusRespon = json["status"] as! Bool
print("Purchase Request - Response status: \(statusRespon)")
if statusRespon == true {
guard let isiData = json["data"] as? [[String: Any]] else {
print("Purchase Request - data is empty")
return
}
for dataIsi in isiData {
guard let listData = dataIsi["list_data"] as? [[String: Any]] else {
print("Purchase Request - list data purchase request is empty")
return
}
for dataList in listData {
if ((dataList["year"] as? NSNull) != nil) {
self.purYear = "-"
}else{
self.purYear = dataList["year"] as! String
}
if ((dataList["tipe"] as? NSNull) != nil) {
self.purType = "-"
}else{
self.purType = dataList["tipe"] as! String
}
// get flow array
guard let flowList = dataList["flow"] as? [[String: Any]] else {
print("Get flow PR is empty")
return
}
listFlowStatus.removeAll()
listFlagPosition.removeAll()
for listFlow in flowList {
self.flowStatus = listFlow["flow_status"] as! String
self.flagPosition = listFlow["flag_position"] as! String
print("=== Flow \(self.flowId) - \(self.flagPosition) ===")
listFlowStatus.append(self.flowStatus)
listFlagPosition.append(self.flagPosition)
}
modelPurchase.append(ModelPurchaseRequest(year: self.purYear, type: self.purType, listFlowSatus: listFlowStatus, listFlowPosition: listFlagPosition))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}else{
print("Get list purchase request response status false")
}
}catch{
print(error.localizedDescription)
}
}.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return modelPurchase.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.collectionView.reloadData()
return cell
}
}
Class CollectionViewCell.swift
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var view: UIView!
}
Class TableViewCell.swift
import UIKit
class TableViewCell: UITableViewCell,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
collectionView.dataSource = self as UICollectionViewDataSource
collectionView.delegate = self as UICollectionViewDelegate
collectionView.reloadData()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return modelPurchase[section].listFlowStatus.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
let positionNow = modelPurchase[indexPath.section].listFlowPosition[indexPath.row]
if positionNow == "Green" {
cell.view.backgroundColor = UIColor.green
}else if positionNow == "Orange" {
cell.view.backgroundColor = UIColor.orange
}else{
cell.view.backgroundColor = UIColor.red
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(modelPurchase[indexPath.section].listFlowPosition[indexPath.row])
}
}
Here JSON:
{
"status": true,
"message": "Data Show Success",
"data": [
{
"list_data": [
{
"rowsnum": "1",
"year": "2018",
"tipe": "PROGRAM",
"flow": [
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Red"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Orange"
}
]
},
{
"rowsnum": "2",
"year": "2018",
"tipe": "PROJECT",
"flow": [
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Red"
},
{
"flow_status": "1",
"flag_position": "Red"
},
{
"flow_status": "1",
"flag_position": "Orange"
}
]
},
{
"rowsnum": "3",
"year": "2018",
"tipe": "PROGRAM",
"flow": [
{
"flow_status": "1",
"flag_position": "Red"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Orange"
},
{
"flow_status": "1",
"flag_position": "Green"
},
{
"flow_status": "1",
"flag_position": "Green"
}
]
}
]
}
]
}
Please change the code as following :
Step 1:
In tableView cellForRowAt method please write:
cell.collectionView.tag = indexPath.row
Step2:
Then in collectionView numberOfItemsInSection method please write :
return modelPurchase[collectionView.tag].listFlowStatus.count
Step 3:
In collectionView cellForItemAt method write :
let positionNow = modelPurchase[collectionView.tag].listFlowPosition[indexPath.row]
Change the code accordingly.It may helps to you .Thank you
Related
In a macOS app, I set NSWindow.backgroundColor = .clear.
When SwiftUI views re-render, their previously rendered versions often get stuck in the background.
Is it a bug, or am I doing something wrong?
Do you know of a workaround?
Environment:
macOS 12.5.1
Xcode 14.0
Thank you in advance.
import SwiftUI
#main
struct MacosPlaygroundApp: App {
var body: some Scene {
WindowGroup("Playground") {
ContentView()
.frame(width: 120, height: 300, alignment: .center)
}
}
}
struct ContentView: View {
private let items: [Item] = [
Item(id: "first", name: "First", sfSymbol: "house"),
Item(id: "second", name: "Second", sfSymbol: "sun.max"),
Item(id: "third", name: "Third", sfSymbol: "cloud"),
Item(id: "fourth", name: "Fourth", sfSymbol: "trash"),
Item(id: "fifth", name: "Fifth", sfSymbol: "scribble"),
]
var body: some View {
ScrollView {
LazyVGrid(columns: [gridItem], alignment: .center, spacing: 10) {
ForEach(items, id: \.id) { item in
itemView(item: item)
}
}
}
.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
if let mainWindow = NSApplication.shared.windows.first(where: { $0.title == "Playground" }) {
mainWindow.backgroundColor = .clear
}
}
}
#ViewBuilder
private func itemView(item: Item) -> some View {
VStack(alignment: .center, spacing: 10) {
Image(systemName: item.sfSymbol)
Text(item.name)
}
.padding()
.background(.pink.opacity(0.5))
.cornerRadius(10)
}
private var gridItem: GridItem {
GridItem(
.adaptive(minimum: 100, maximum: 100),
spacing: 10,
alignment: .top
)
}
private struct Item {
let id: String
let name: String
let sfSymbol: String
}
}
I found a workaround:
.backgroundColor = .white.withAlphaComponent(0.000001), instead of .clear.
The window still appears transparent (enough), and I cannot see the rendering bug happen.
I have a simple amChart5 chart.
I would like to change the colors of the text that displays on the axes and assign a different color to each of these elements.
What I have:
What I want:
The documentation explains that you can change the color but it applies to the whole axis, to all elements at the same time.
Do you know if there is a way to treat each element individually?
A nice solution is to use an adapter like so:
xAxis.get("renderer").labels.template.adapters.add("fill", (fill, target) => {
if (target.dataItem && target.dataItem.dataContext) {
let category = target.dataItem.dataContext.category;
if (category === "Category 1") {
return "#ff0000";
} else if (category === "Category 2") {
return "#00ff00";
} else {
return "#0000ff";
}
}
return fill;
});
Full code:
am5.ready(() => {
let root = am5.Root.new("chartdiv");
let chart = root.container.children.push(am5xy.XYChart.new(root, {}));
let legend = chart.children.push(am5.Legend.new(root, {
centerX: am5.p50,
x: am5.p50
}));
let data = [
{
"category": "Category 1",
"value1": 10,
"value2": 1
},
{
"category": "Category 2",
"value1": 20,
"value2": 7
},
{
"category": "Category 3",
"value1": 15,
"value2": 3
}
];
let xAxis = chart.xAxes.push(am5xy.CategoryAxis.new(root, {
categoryField: "category",
renderer: am5xy.AxisRendererX.new(root, {})
}));
xAxis.data.setAll(data);
// ==================================================
xAxis.get("renderer").labels.template.adapters.add("fill", (fill, target) => {
if (target.dataItem && target.dataItem.dataContext) {
let category = target.dataItem.dataContext.category;
if (category === "Category 1") {
return "#ff0000";
} else if (category === "Category 2") {
return "#00ff00";
} else {
return "#0000ff";
}
}
return fill;
});
// ==================================================
let yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {})
}));
function makeSeries(name, fieldName) {
let series = chart.series.push(am5xy.ColumnSeries.new(root, {
name: name,
xAxis: xAxis,
yAxis: yAxis,
categoryXField: "category",
valueYField: fieldName
}));
series.data.setAll(data);
legend.data.push(series);
}
makeSeries("Series 1", "value1");
makeSeries("Series 2", "value2");
});
#chartdiv {
width: 100%;
height: 350px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<div id="chartdiv"></div>
When I first launch my app the toolbar icons are shown and work fine, but they are initially greyed out until mousing over the button.
First run of the app:
and then mouse over:
Here is the code:
import SwiftUI
struct ContentView: View
{
#State var mainList:[String] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "Indigo", "Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whisky", "Xray", "Yankee", "Zulu"]
#State var selectedItem:String? = "Echo"
var body: some View
{
NavigationView
{
List()
{
ForEach(mainList, id: \.self)
{item in
NavigationLink(destination: DetailView(item: item), tag: item, selection: $selectedItem, label:
{
Text("\(item)")
})
}
}
}
.toolbar
{
Button(action: {addNewItem()})
{
Label("Select", systemImage: "square.and.pencil")
}
}
}
func addNewItem()
{
print ("Add item")
}
}
struct DetailView: View
{
#State var item: String
var body: some View
{
Text(item)
}
}
This is in Xcode 12.5.1 and Xcode 13.0 beta.
I would have thought that the toolbar should be enabled at active with this code. Is it a bug or am I doing something wrong?
The bug seems to be in Button(). Here is a workaround that works for me. The only downside is that it lacks the visual feedback of the Button when pressed.
.toolbar
{
Label("Select", systemImage: "square.and.pencil")
.onTapGesture(perform: {addNewItem()})
}
I want to export multiple am4charts with layout in one PDF like it was in V3
https://www.amcharts.com/docs/v3/tutorials/exporting-pdf-with-multiple-charts-and-related-info/
Please follow the new tutorial how to generate a multi-content PDF.
You can add another chart as extraSprites from version 4.2.0 as in:
chart.exporting.extraSprites.push(chart2);
Check more about how to add an extra element here.
Previous Recommendation
I recommend you to check the answer for this issue: https://github.com/amcharts/amcharts4/issues/743
amCharts uses PDFMake to generate PDFs, which allows you to assemble PDF as you whish.
Please check a simpler example how your code could look like:
// Use this method to call the export functionality
let exportCharts = async (charts) => {
// Map chats to images
let images = await Promise.all(charts.map(async (chart) => {
return await new Promise((resolve, reject) => {
let getImage = () => {
resolve(chart.exporting.getImage('png'));
}
// Get the image if the chart is ready
if (chart.isReady())
getImage();
// Get the image when the chart is ready
else
chart.events.on('ready', () => getImage());
});
}));
// Begin PDF layout
const layout = {
content: []
};
// Add charts
layout.content = images.map((image) => {
return {
image: image,
fit: [523, 300]
};
});
// Finally, download our PDF
charts[0].exporting.pdfmake.then(function(pdfMake) {
pdfMake.createPdf(layout).download("amcharts4.pdf");
});
}
// Call exports with all the charts you want exported
exportCharts([chart1, chart2]);
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart1 = am4core.create('chart-1', am4charts.XYChart3D);
// Add data
chart1.data = [{
"country": "USA",
"visits": 4025
}, {
"country": "China",
"visits": 1882
}, {
"country": "Japan",
"visits": 1809
}, {
"country": "Germany",
"visits": 1322
}, {
"country": "UK",
"visits": 1122
}, {
"country": "France",
"visits": 1114
}, {
"country": "India",
"visits": 984
}, {
"country": "Spain",
"visits": 711
}, {
"country": "Netherlands",
"visits": 665
}, {
"country": "Russia",
"visits": 580
}, {
"country": "South Korea",
"visits": 443
}, {
"country": "Canada",
"visits": 441
}, {
"country": "Brazil",
"visits": 395
}, {
"country": "Italy",
"visits": 386
}, {
"country": "Australia",
"visits": 384
}, {
"country": "Taiwan",
"visits": 338
}, {
"country": "Poland",
"visits": 328
}];
// Create axes
let categoryAxis = chart1.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.renderer.labels.template.rotation = 270;
categoryAxis.renderer.labels.template.hideOversized = false;
categoryAxis.renderer.minGridDistance = 20;
categoryAxis.renderer.labels.template.horizontalCenter = "right";
categoryAxis.renderer.labels.template.verticalCenter = "middle";
categoryAxis.tooltip.label.rotation = 270;
categoryAxis.tooltip.label.horizontalCenter = "right";
categoryAxis.tooltip.label.verticalCenter = "middle";
let valueAxis = chart1.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Countries";
valueAxis.title.fontWeight = "bold";
// Create series
var series = chart1.series.push(new am4charts.ColumnSeries3D());
series.dataFields.valueY = "visits";
series.dataFields.categoryX = "country";
series.name = "Visits";
series.tooltipText = "{categoryX}: [bold]{valueY}[/]";
series.columns.template.fillOpacity = .8;
var columnTemplate = series.columns.template;
columnTemplate.strokeWidth = 2;
columnTemplate.strokeOpacity = 1;
columnTemplate.stroke = am4core.color("#FFFFFF");
columnTemplate.adapter.add("fill", (fill, target) => {
return chart1.colors.getIndex(target.dataItem.index);
})
columnTemplate.adapter.add("stroke", (stroke, target) => {
return chart1.colors.getIndex(target.dataItem.index);
})
chart1.cursor = new am4charts.XYCursor();
chart1.cursor.lineX.strokeOpacity = 0;
chart1.cursor.lineY.strokeOpacity = 0;
// Create chart instance
var chart2 = am4core.create('chart-2', am4charts.PieChart);
// Add data
chart2.data = [ {
"country": "Lithuania",
"litres": 501.9
}, {
"country": "Czech Republic",
"litres": 301.9
}, {
"country": "Ireland",
"litres": 201.1
}, {
"country": "Germany",
"litres": 165.8
}, {
"country": "Australia",
"litres": 139.9
}, {
"country": "Austria",
"litres": 128.3
}, {
"country": "UK",
"litres": 99
}, {
"country": "Belgium",
"litres": 60
}, {
"country": "The Netherlands",
"litres": 50
} ];
// Add and configure Series
var pieSeries = chart2.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
// Disable labels
pieSeries.labels.template.disabled = true;
pieSeries.ticks.template.disabled = true;
// Use this method to call the export functionality
let exportCharts = async (charts) => {
// Map chats to images
let images = await Promise.all(charts.map(async (chart) => {
return await new Promise((resolve, reject) => {
let getImage = () => {
resolve(chart.exporting.getImage('png'));
}
// Get the image if the chart is ready
if (chart.isReady())
getImage();
// Get the image when the chart is ready
else
chart.events.on('ready', () => getImage());
});
}));
// Begin PDF layout
const layout = {
content: []
};
// Add charts
layout.content = images.map((image) => {
return {
image: image,
fit: [523, 300]
};
});
// Finally, download our PDF
charts[0].exporting.pdfmake.then(function(pdfMake) {
pdfMake.createPdf(layout).download("amcharts4.pdf");
});
}
document.getElementById('print-to-pdf').addEventListener('click', () => {
// Call exports with all the charts you want exported
exportCharts([chart1, chart2]);
});
.ui.segment {
padding: 0;
}
body > .ui.container {
margin-top: 3em;
margin-bottom: 4em;
}
body > .ui.container > .ui.segment {
height: 36em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet"/>
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<script src="https://cdn.jsdelivr.net/npm/viewport-action#0.2.1/dist/viewportAction.min.js"></script>
<div class="ui container">
<button id="print-to-pdf" class="ui blue button">Print</button>
<div id="chart-1" class="ui segment">
<div class="ui active loader"></div>
</div>
<div id="chart-2" class="ui segment">
<div class="ui active loader"></div>
</div>
</div>
I'm trying to create a power BI custom visual.I'm currently working on creating a pie chart.
The pie chart visual is being displayed.
I have defined Legend as a boolean property and currently trying to render a legend for the piechart when show property of Legend value is set totrue .
But even when settings.Legend.show is true, No Legend is being shown.
I'm using d3.js to create the visuals.
Can someone help?
Here's my visual.ts
module powerbi.extensibility.visual {
"use strict";
interface Data
{
quantity: number;
category: string;
color:string;
selectionId:ISelectionId;
}
interface PieChartArc {
datapoints:Data[];
setting:pieChartSettings;
dataview:DataView[];
}
interface pieChartSettings
{
Legend :
{
show:boolean;
};
}
interface LegendValues
{
category:string;
color:string;
selection:ISelectionId;
}
function visualTransform(options:VisualUpdateOptions,host:IVisualHost) : PieChartArc
{
let dataViews=options.dataViews;
let defaultSetting :pieChartSettings = {
Legend:{
show:false,
}
};
let viewModel:PieChartArc=
{
datapoints:[],
setting : defaultSetting,
dataview: dataViews
};
if (!dataViews
|| !dataViews[0]
|| !dataViews[0].categorical
|| !dataViews[0].categorical.categories
|| !dataViews[0].categorical.categories[0].source
|| !dataViews[0].categorical.values)
return viewModel;
let categorical=dataViews[0].categorical;
let category=categorical.categories[0];
let dataValue=categorical.values[0];
let pieChartData:Data[]=[];
let colorPalette:IColorPalette=host.colorPalette;
let objects=dataViews[0].metadata.objects
let pieChartSetting:pieChartSettings={
Legend:{
show: getValue<boolean>(objects,'Legend','show',defaultSetting.Legend.show)
}
}
for(let i=0;i<Math.max(category.values.length,dataValue.values.length);i++)
{
pieChartData.push({
quantity:<number>dataValue.values[i],
category:<string>category.values[i],
color:colorPalette.getColor(<string>category.values[i]).value,
selectionId:host.createSelectionIdBuilder()
.withCategory(category, i)
.createSelectionId()
});
console.log(pieChartData[i].color);
}
return {
datapoints:pieChartData,
setting:pieChartSetting,
dataview:dataViews
};
}
export class PieChart implements IVisual {
private target: HTMLElement;
private settings: VisualSettings;
private textNode: Text;
private pieChartContainer: d3.Selection<SVGElement>;
private arc: any;
private host: IVisualHost;
private selectionManager:ISelectionManager;
private svg: d3.Selection<SVGElement>;
private legend:d3.Selection<SVGElement>;
private g: any;
private pie: any;
private color: string;
private tooltipServiceWrapper: ITooltipServiceWrapper;
private pieSettings:pieChartSettings;
static data:DataView[];
static config=
{
solidOpacity:1,
transparentOpacity:0.5,
};
constructor(options: VisualConstructorOptions) {
console.log('Visual constructor', options);
this.target = options.element;
this.host=options.host;
this.selectionManager=options.host.createSelectionManager();
this.legend=d3.select(options.element);
let svg=this.svg=d3.select(options.element)
.append('svg')
.classed("pieChart",true)
;
this.pieChartContainer=svg.append('g').classed('pieChartContainer',true);//.attr('transform','translate('+100+',' +100+')');
this.tooltipServiceWrapper = createTooltipServiceWrapper(this.host.tooltipService, options.element);
}
public update(options: VisualUpdateOptions) {
// let legendModel : LegendValues[] = legendTransform(options,this.host);
let viewModel: PieChartArc = visualTransform(options, this.host);
let settings=this.pieSettings=viewModel.setting;
let category=options.dataViews[0].categorical.categories[0];
let dataValue=options.dataViews[0].categorical.values[0];
let legend=this.legend;
let legendEnumerate:LegendValues[];
// shows legend
if(settings.Legend.show)
{ //this.svg.append("text").text("Hello");
for(let i=0;i<category.values.length;++i)
{
legendEnumerate.push({
category:<string>category.values[i],
color:<string>dataValue.values[i],
selection:this.host.createSelectionIdBuilder()
.withCategory(category, i)
.createSelectionId()
});
}
let leg=this.legend.append('svg');
for(let i=0;i<Math.max(category.values.length,dataValue.values.length);++i)
{
// this.legend.html(legendEnumerate[i].category).attr("transform","translate(" + i*20 +",0)")
// leg.a
leg.append('circle')
.attr('cx',20)
.attr('cy',20)
.attr('r',8)
.attr('fill',legendEnumerate[i].color)
.attr("transform","translate(" + i*20 +",0)")
;
leg.append('text')
.text(legendEnumerate[i].category)
.attr("transform","translate(" + i*30 +",0)")
;
}
}
PieChart.data=options.dataViews;
let width=options.viewport.width;
let height=options.viewport.height;
let radius=Math.min(width,height)/2;
this.svg.attr({
width: width-20,
height: height-20,
});
this.arc=d3.svg.arc()
.innerRadius(0)
.outerRadius(radius-20);
this.pie = d3.layout.pie<Data>().value((d: Data):number => d.quantity).sort(null);
let fill = ((d):string=> d.data.color);
let tf = (d: Data) => `translate(${this.arc.centroid(d)})`;
let text = d => d.data.category;
this.svg.append('g');
this.g=this.svg.selectAll('.arc')
.data(this.pie(viewModel.datapoints))
.enter()
.append('g')
.attr('class', 'arc')
.data(this.pie(viewModel.datapoints))
// .attr("fill",fill)
;
let path= this.g.append('path')
.attr('d', this.arc)
.attr('fill',fill)
.attr('fill-opacity',1)
//.style("stroke","black")
.attr("stroke-width","0.8");
this.g.append('text').attr('transform', tf).text(text).attr('fill',"white");
this.tooltipServiceWrapper.addTooltip(path,
(tooltipEvent: TooltipEventArgs<number>) => PieChart.getTooltipData(tooltipEvent.data),
(tooltipEvent: TooltipEventArgs<number>) => null);
let selectionManager = this.selectionManager;
path.on("click",function(d)
{
// path.attr('fill','blue');
selectionManager.select(d.data.selectionId).then((ids: ISelectionId[])=>
{
path.attr('fill-opacity',ids.length>0? PieChart.config.transparentOpacity:PieChart.config.solidOpacity);
d3.select(this).attr('fill-opacity',PieChart.config.solidOpacity);
(<Event>d3.event).stopPropagation;
});
});
path.exit()
.remove();
}
private static parseSettings(dataView: DataView): VisualSettings {
return VisualSettings.parse(dataView) as VisualSettings;
}
/**
* This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
* objects and properties you want to expose to the users in the property pane.
*
*/
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstance[] | VisualObjectInstanceEnumerationObject {
// return VisualSettings.enumerateObjectInstances(this.settings || VisualSettings.getDefault(), options);
let objectName=options.objectName;
let objectEnumeration:VisualObjectInstance[]=[];
switch(objectName)
{
case 'Legend':
objectEnumeration.push({
objectName:objectName,
properties:{
show:this.pieSettings.Legend.show,
},
selector:null
});
};
return objectEnumeration;
}
private static getTooltipData(value: any): VisualTooltipDataItem[] {
return [{
displayName:PieChart.data[0].metadata.columns[1].displayName,
value: value.value.toString(),
color: value.data.color,
header:value.data.category
}];
}
}
}
here's my capabilities.json
{
"dataRoles": [
{
"displayName": "Category",
"name": "category",
"kind": "Grouping"
},
{
"displayName": "Measure",
"name": "measure",
"kind": "Measure"
}
],
"objects": {
"dataPoint": {
"displayName": "Data colors",
"properties": {
"defaultColor": {
"displayName": "Default color",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"showAllDataPoints": {
"displayName": "Show all",
"type": {
"bool": true
}
},
"fill": {
"displayName": "Fill",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
},
"fillRule": {
"displayName": "Color saturation",
"type": {
"fill": {}
}
},
"fontSize": {
"displayName": "Text Size",
"type": {
"formatting": {
"fontSize": true
}
}
}
}
},
"Legend":{
"displayName": "Legend",
"properties": {
"show" :{
"displayName": "Legend",
"type": {
"bool": true
}
}
}
}
},
"dataViewMappings": [
{
"categorical": {
"categories": {
"for": {
"in": "category"
},
"dataReductionAlgorithm": {
"top": {}
}
},
"values": {
"select": [
{
"bind": {
"to": "measure"
}
}
]
}
},
"conditions":[
{ "category":{
"max":1
},
"measure":{
"max":1
}
}
]
}
]
}