famo.us: Modify content in GridLayout - css

is it possible to modify the content of a surface (used within GridLayout) without using CSS? For example to center the text?
Basic example:
function createGrid( section, dimensions, menuData ) {
var grid = new GridLayout({
dimensions: dimensions
});
var surfaces = [];
grid.sequenceFrom(surfaces);
for(var i = 0; i < dimensions[1]; i++) {
surfaces.push(new Surface({
content: menuData[i].title,
size: [undefined, undefined],
properties: {
backgroundColor: "#ff0000",
color: "white",
textAlign: 'center',
}
}));
}
return grid;
}
I added the center property, but I also want to have the content in the middle of my surface. Do I have to use CSS or is there another way?
I tried adding another View/Surface within this Surface and added the align/origin modifier. Didn't work: I still had to adjust the origin/align values for the specific (browser) layout ...

I'm not so sure about you first question, but I can answer the second one.
text-alignhelps you horizontally center your content. So the problem is how to do it vertically.
The cleanest way to do it is to set the line-height the same as the containing div's height. In your case, there are two ways to do it:
1) calculate the height of the grid. For example, if you have a 9*9 GridLayout for the whole screen, then we will have gridHeight = window.innerHeight/9. Then you just need to add lineHeight: gridHeight to your properties object.
check http://jsfiddle.net/mrwiredancer/veLpbmmo/2/ for full exmaple
2) if you are not able to calculate the height of the grid beforehand, you can center a fixed-height(smaller than the grid's height) surface in the middle of the grid. For example, your GridLayout is contained in a dynamic view, but you're sure that your grid is no less than 20px high. Then you can do this:
var container, surface, __height = 20;
for(var i = 0; i < dimensions[1]; i++) {
container = new Container({ //View works as well
properties: {
backgroundColor: '#FF0000'
}
})
surface = new Surface({
content: menuData[i].title,
size: [undefined, __height],
properties: {
lineHeight: __height+'px', //same as surface's height
color: "white",
textAlign: 'center',
}
});
container.add(new Modifier({origin: [.5, .5]})).add(surface);
surfaces.push(container);
}
check http://jsfiddle.net/mrwiredancer/uxq30yp9/1/ for full example

Related

Echart Dragging points with more than 1 graphical element issue

I have created a chart with 3 points. I have added two graphical elements as circle and rectangle (line) for dragging the points.
Circle dragging should apply for all three points in the graph as in the expected behavior screenshot below.
Line dragging is a vertical shift for graph to move it vertically.
Circle dragging does not apply for all 3 points when I return both graphical elements in the elements array as in the code. It just applies only for 1st point.
When I return one graphical element at a time it works.
Current Behaviour
image of how chart works now
Below I have included the code which returns graphic elements
myChart.setOption({
graphic: data.map(function (item, dataIndex) {
let rec = {
type: 'group',
left: 'center',
position: myChart.convertToPixel('grid', item),
draggable: 'vertical',
ondrag: function (dx, dy) {
onPointDraggingLine(dataIndex, [this.x, this.y]);
},
children: [
{
type: 'rect',
top: '200x',
shape: {
width: 470,
height: 0
},
style: {
stroke: 'gray',
lineWidth: 5,
lineDash: [6]
},
cursor: 'move'
}
]
};
let onlyCrc = {
type: 'circle',
position: myChart.convertToPixel('grid', item),
draggable: true,
ondrag: function (dx, dy) {
onPointDragging(dataIndex, [this.x, this.y]);
},
shape: {
cx: 0,
cy: 0,
r: symbolSize / 2
},
invisible: false,
z: 100,
cursor: 'move'
};
return { elements: [rec, onlyCrc] };
})
});
I have tried to return graphical elements as array of objects .And I have tried by giving a condition for dataIndex while mapping. but didn't work. Expected behavior is as below.
Expected Behavior.
image of how chart should work
Below I have attached the whole code I tried in Codepen.
Link to Minimal Reproduction
https://codepen.io/rushaidrilaf/pen/bGKONRj
I was able to Solve this. Started to resolve it by pointing the dragging function to 2nd point in the graph and updating the position of circular graphical element while dragging the horizontal line.
solution can be viewed from this link
https://codepen.io/rushaidrilaf/pen/bGKONRj
enter code here

CanvasJS charts take up entire row when using flexbox

I am currently using CanvasJS for pie charts in a project done in ReactJS. When a search for a particular person is done, I render 4 pie charts displaying information. I would like to render the pie charts side-by-side (as the space allows) over multiple rows using Flexbox.
Currently, when the pie charts render, each CanvasJSChart takes up the entire width of the row. In the picture below, you can see that although each pie chart takes up ~1/3 of of the table (the "Trial Version" and "Canvasjs.com" are not fixed in position relative to the pie chart and can move closer to it, depending on the size of the container), the container is the width of the row. I would ideally like each row to contain 2 pie charts (but not fixed to allow the application to work better on small screens).
This is my CSS section.
.container {
display:flex;
flex-wrap: row wrap;
}
When I did not have the flex-wrap: row wrap; line, the charts would individually take up less space and all remain on the same row:
So when I do try to have the charts wrap around, I'm not sure why the size of the container changes to the entire row. Below is my code that renders the charts (in a component named Accuracy when I search a name:
class Contestant extends Component{
constructor(props){
super(props)
}
render(){
var name = this.props.data[0];
var data = this.props.data[1];
let fjText = null
let fj = null
if (data.FJCorrect+data.FJIncorrect>0){
fj = <Accuracy numberCorrect={data.FJCorrect} numberIncorrect={data.FJIncorrect}
overallAccuracy = {data.FJAccuracy}/>
}
let tiebreak = null
let tiebreakText = null
if (data.TiebreakCorrect+data.TiebreakIncorrect>0){
tiebreak = <Accuracy numberCorrect={data.TiebreakCorrect}
numberIncorrect={data.TiebreakIncorrect}overallAccuracy = {data.TiebreakAccuracy} />
}
return(
<div className = "container" >
<Accuracy numberCorrect={data.numberCorrect} numberIncorrect={data.numberIncorrect}
overallAccuracy = {data.overallAccuracy}/>
<Accuracy numberCorrect={data.JCorrect} numberIncorrect={data.JIncorrect}
overallAccuracy = {data.JAccuracy}/>
<Accuracy numberCorrect={data.DJCorrect} numberIncorrect={data.DJIncorrect}
overallAccuracy = {data.DJAccuracy}/>
{fj}
{tiebreak}
</div>
)
}
}
export default Contestant
and below is my code that renders a Contestant component:
class Search extends Component{
constructor(){
super()
this.state = {search: "",
isLoading: true,
result: "",
searchType: null
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleSearch = this.handleSearch.bind(this);
}
handleSearch(searchStr){
//Takes in text and finds data of corresponding person
}
handleChange(event){
//In case someone is searching for a new term, we have to reset search query type
if (this.state.searchType !== null){
this.setState({isLoading: true})
}
this.setState({search: event.target.value});
}
handleSubmit() {
this.setState({isLoading: false, result: this.handleSearch(this.state.search)})
}
render(){
return(
<div>
<input type="text" value={this.state.search} onChange={this.handleChange} placeholder={...} />
<button type="submit" onClick={this.handleSubmit}>Search</button>
{this.state.result.length === 0 ? null: <Contestant data={this.state.result}/>}
</div>
)
}
}
export default Search
My CanvasJS pie chart has the default settings as on the linked website (with only data points changed), so I'm not sure why the size of the charts change depending on whether I wrap my Flexbox cells.
class Accuracy extends Component{
constructor(props){
super(props)
}
render(){
var correctAccuracy = ((this.props.overallAccuracy).toFixed(2)).toString()
var incorrectAccuracy = ((100-this.props.overallAccuracy).toFixed(2)).toString()
var options = {
animationEnabled: false,
animationEnabled: true,
animationDuration: 500,
backgroundColor: "#F0F8FF",
height: 260,
data: [{
type: "pie",
startAngle: 300,
toolTipContent: "{accuracy}%",
indexLabelFontSize: 16,
indexLabel: "{label}:{y}",
dataPoints: [
{ y: this.props.numberCorrect, label: "Correct", accuracy: correctAccuracy },
{ y: this.props.numberIncorrect, label: "Incorrect", accuracy: incorrectAccuracy},
]
}]
}
return (
<CanvasJSChart options = {options}/>
)
}
}
export default Accuracy
Any help would be greatly appreciated! I've been stuck on this for a couple of days
From the first screencap, it seems like your problem is that the width of your pie chart containers is set to 100%. This means that each container will be 100% of its parent--in this case the .container div. Your CSS should look like this:
.container {
display: flex;
flex-wrap: row-wrap;
}
.piechart-container {
width:50%;
}
And of course you need to add the "piechart-container" classname to you piechart container divs. I didn't try this out so let me know if it works. You may have to set the width to be slightly less than 50% or change the max-width property as well. Instead of width:50% you could do flex:0 0 50% which is a flexbox item property meaning "set an initial width of 50% and don't allow any growing or shrinking."
Edit: just now seeing that you want some flexibility. You'd probably be better off setting the container widths in terms of pixels instead of percentages so that when the screen gets small enough they overflow to be one chart per row. I would recommend looking up "media queries" and setting the CSS so that if the screen width goes below a certain number, a different set of attributes takes place (i.e. smaller charts, different wrapping behavior)

GeometryReader not generating correct screen height?

public var body: some View
{
ZStack{
GeometryReader { geometry in
RoundedRectangle(cornerRadius: 25, style: .continuous)
.frame(width: geometry.size.width*1.00, height: geometry.size.height*1.00)
.zIndex(0)
}
}
}
I'm using GeometryReader to draw a rounded rectangle to fill up the entire watch screen, this looks fine on a 38mm watch simulator, but as I increase the watch size to 40, 42, 44mm I noticed that the height is not filling up the whole screen. I have to adjust my multiple to say 1.1 for example to fill up more of the screen.
Can someone tell me if I am using GeometryReader incorrectly?
Unless you really need the full functionality of the geometry reader, to actually measure the size of the object of the screen, then I think you could achieve the effect you want by setting the frame's maxWidth and maxHeight to .infinity and by ignoring the safe area on the bottom.
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.bottom)
}
}
Note that when you use a ZStack the order of the items in it determine the order on the screen. The first item in the stack will be at the bottom, and then each item will be layered on top.

change the legend.y property on browser resize

we use the highchart control with Angular and bootstrap.
To adjust the vertical space between the chart and the legend (both are rendered by highchart as svg elements), we set the y property of the legend on page load (in the controller) like this:
$scope.chartContracts = {
options: {
chart: {
type: 'pie',
marginBottom: 50
},
legend : {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom',
x: 0,
y: 4,
Now in one of the Bootstraps layouts, the spacing (y) should be -10 in stead of 4 because for some reason an extra spacing is added.
So it should be based on media query or something similar I guess?
The question is how to do this... I tried with css but I can't seem to style SVG elements (they are called <g>)?
You can check window width and then return correct value.
var wWidth = $(window).width(),
value;
if(wWidth < 400) {
value = 5;
} else {
value = 10;
}
//scope
y: value

angular ng-grid maxWidth not used

I am trying to create some autosizing properties for an angular ng-grid element:
for (var i = 0; i < $scope.dates.length; i++) {
var dateElement = {
field: 'reportMap.' + $scope.dates[i] + '.hours | round',
displayName: i + 1,
minWidth: "27px",
maxWidth: "46px"
};
if ($scope.holidays.indexOf(i + 1) != -1) {
dateElement.cellTemplate = 'app/partials/gridCell.html';
}
$scope.columns.push(dateElement);
.....
$scope.gridOptions = {
data: 'monthlyReports',
columnDefs: 'columns',
plugins: [new ngGridFlexibleHeightPlugin()],
enableRowSelection: false,
enableColumnResize: true,
enableSorting: false,
enableCellSelection: true
};
However, when the field data gets longer than 4 characters the content is hidden. I.e. the width is not increased. I could be using width: "auto" but i need to limit the sizing of th columns somewhat...
Why is the column width not increased when the conent gets longer than 27px?
This is what i get setting the width to auto for my date elements:
This is what i want, dynamic width depending on content! (i also want less padding around the number and the left and right sides of the cell, see the wide cell)
Ovveriding the cell properties did the trick in this case, just increasing the constant width one pixel to 28px and overriding the padding made it look good.
ngCellText {padding: 2px; text-align: center;}

Resources