问:
Why is my SVG file not using my font file?
I have this SVG file in the same directory as this font's TTF file.

```<code><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.1"
  width="150"
  height="100"
  viewBox="0 0 150 100"
>
  <style type="text/css">
    @font-face {
      font-family: "easyPrint";
      src: url('./easy-print.regular.ttf');
    }
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
  <text
    x="10"
    y="80"
    font-size="25"
  >
    TEST
  </text>
</svg>
</code>```

When I do this, I get two different fonts. The one that should be my custom font is the same font you see if you give it gibberish for a font-family. Which is different from the default.

I've tried with an OTF file as well. The specific font isn't important. I'm just trying to produce a bunch of SVG images of text with a specific font.

答:
If you need your svg files to be perfectly self contained,

you should consider embedding the font-files as base64 resource (using a tool like transfonter):

1. Example: font embedded as base64

This svg would always display the custom font (inlined svg, referenced in img element, opened directly in browser.)
 (Letter a is not contained in the reduced character subset)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">

  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TESTa
  </text>
</svg>```
</div>
</div>
</p>
<p>You can significantly reduce file size by subsetting your font:<br />
Only selected characters will be available.</p>
<p><img src="https://i.stack.imgur.com/GEves.png" alt="transfonter settings" /></p>
<h2>2. Example: Svg2Png</h2>
<p>This approach requires the font to be inlined as dataURL.<br />
Otherwise the png output will render a default font like Times.</p>
<p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>function svg2Png(selector) {
  const svgEl = document.querySelector(selector);
  let svgVB = svgEl.getAttribute('viewBox');
  let svgVBArr = svgVB ? svgVB.split(' ') : '';
  let svgVBW = svgVBArr ? svgVBArr[2] : '';
  let svgVBH = svgVBArr ? svgVBArr[3] : '';

  let svgClientBB = svgEl.getBoundingClientRect();
  let svgClientW = svgClientBB.width;
  let svgClientH = svgClientBB.height;

  let svgBB = svgEl.getBBox();
  let svgW = svgVBW? svgVBW : svgBB.width;
  svgW = svgClientW > svgW ? svgClientW : svgW;
  let svgH = svgVBH? svgVBH : svgBB.height;
  svgH = svgClientH > svgH ? svgClientH : svgH;

  let blob = new Blob([svgEl.outerHTML], {type: 'image/svg+xml'});
  let URL = window.URL;
  let blobURL = URL.createObjectURL(blob);
  let tmpImg = new Image();
  tmpImg.src = blobURL;
  tmpImg.width = svgClientW > svgW ? svgClientW : svgW;
  tmpImg.height = svgClientH > svgH ? svgClientH : svgH;

  tmpImg.onload = () => {
    let canvas = document.createElement("canvas");
    canvas.width = svgW;
    canvas.height = svgH;
    let context = canvas.getContext("2d");

    // draw blob img to canvas with some delay
    setTimeout(function () {
      context.drawImage(tmpImg, 0, 0, svgW, svgH);
      let pngDataUrl = canvas.toDataURL();
      let svgImg = document.createElement("img");
      svgImg.width = svgW;
      svgImg.height = svgH;
      svgImg.class = "svgImg";
      svgImg.src = pngDataUrl;
      // just additional wrapping for example usage
      let imgWrp = document.createElement("div");
      imgWrp.setAttribute("class", "img-wrp");
      imgWrp.appendChild(svgImg);
      document.body.appendChild(imgWrp);
    }, 300);
  };
}</code>```

    svg,
        img{
            border:1px solid #ccc
        }

        .svg-wrp{
            position:relative;
            overflow:auto;
            resize:both;
            width:50%;

        }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="btn-wrp">
  <button type="button" onclick="svg2Png('svg')">svg2Png</button>
</div>

<div class="svg-wrp">

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
    font-family: 'easyPrint';
     src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
    font-weight: normal;
}
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
</svg>

</div></code>```

3. Example: create svg with text rendered as path

This example employs the awesome opentype.js library.

Opentype.js has a handy function font.getPath() allowing you to render string as a svg <path> element based on the before loaded font file.

let svgcontainer = document.querySelector('#svgcontainer');
let inputText = document.querySelector('#inputText');
// opentype.js accepts only ttf and otf
let fontFile = 'https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf';
inputText.addEventListener('change', function(e) {
  let testString = e.currentTarget.value;
  let params = {
    string: testString,
    font: fontFile,
    fontSize: 100,
    x: 0,
    y: 0,
    decimals: 3
  }
  text2Path(params)
})

//default
let params = {
  string: inputText.value,
  font: fontFile,
  fontSize: 100,
  x: 0,
  y: 0,
  decimals: 3
}
text2Path(params)

function text2Path(params) {
  opentype.load(params.font, function(err, font) {
    if (!err) {
      let options = params.options;
      let path = font.getPath(params.string, params.x, params.fontSize, params.fontSize, options);
      let textPath = path.toSVG(params.decimals);
      let newSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      newSvg.classList.add('svgText');
      newSvg.setAttribute('xmlns', "http://www.w3.org/2000/svg");
      newSvg.insertAdjacentHTML('beforeend', textPath);
      svgcontainer.appendChild(newSvg);

      // adjust bbox
      let bb = newSvg.getBBox();
      newSvg.setAttribute('viewBox', '0 0 ' + (bb.width + bb.x) + ' ' + (params.fontSize * 1.5));

      //add downloadbtn
      let btnDownload = document.createElement("a");
      btnDownload.setAttribute('download', 'font-' + params.string + '.svg');
      btnDownload.textContent = 'Download';
      let dataURl = getDataUrl(newSvg.outerHTML, 'image/svg+xml');
      btnDownload.href = dataURl;
      svgcontainer.appendChild(btnDownload)

    } else {
      console.log('Font could not be loaded: ' + err);
    }
  });
}

function getDataUrl(str, mime) {
  let dataUrl = 'data:' + mime + ';base64,' + btoa(unescape(encodeURIComponent(str)))
  return dataUrl;
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.svgText {
  height: 10em;
  display: inline-block;
  border: 1px solid #ccc;
}

a {
  display: block
}</code>```

    <input id="inputText" type="text" value="Test">

```

Alternative: convert text to path in graphic editor

This is probably the most convenient solution.

Make sure the desired font is installed locally (in you OS).

Open your svg in an graphic editor like inkscape.

select you <text> elements and convert them to paths:

inkscape: Path / Object to path

Adobe Illustrator: Type / Create Outlines

Body:
I have this SVG file in the same directory as this font's TTF file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
    "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.1"
  width="150"
  height="100"
  viewBox="0 0 150 100"
>

  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
  <text
    x="10"
    y="80"
    font-size="25"
  >
    TEST
  </text>
</svg>

When I do this, I get two different fonts. The one that should be my custom font is the same font you see if you give it gibberish for a font-family. Which is different from the default.

I've tried with an OTF file as well. The specific font isn't important. I'm just trying to produce a bunch of SVG images of text with a specific font.

Body:
If you need your svg files to be perfectly self contained,

you should consider embedding the font-files as base64 resource (using a tool like transfonter):

1. Example: font embedded as base64

<p>This svg would always display the custom font (inlined svg, referenced in img element, opened directly in browser.)<br /> (Letter a is not contained in the reduced character subset)</p>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
    font-family: 'easyPrint';
     src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
    font-weight: normal;
}
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TESTa
  </text>
</svg>

You can significantly reduce file size by subsetting your font:

Only selected characters will be available.

2. Example: Svg2Png

This approach requires the font to be inlined as dataURL.

Otherwise the png output will render a default font like Times.

function svg2Png(selector) {
  const svgEl = document.querySelector(selector);
  let svgVB = svgEl.getAttribute('viewBox');
  let svgVBArr = svgVB ? svgVB.split(' ') : '';
  let svgVBW = svgVBArr ? svgVBArr[2] : '';
  let svgVBH = svgVBArr ? svgVBArr[3] : '';

  let svgClientBB = svgEl.getBoundingClientRect();
  let svgClientW = svgClientBB.width;
  let svgClientH = svgClientBB.height;

  let svgBB = svgEl.getBBox();
  let svgW = svgVBW? svgVBW : svgBB.width;
  svgW = svgClientW > svgW ? svgClientW : svgW;
  let svgH = svgVBH? svgVBH : svgBB.height;
  svgH = svgClientH > svgH ? svgClientH : svgH;

  let blob = new Blob([svgEl.outerHTML], {type: 'image/svg+xml'});
  let URL = window.URL;
  let blobURL = URL.createObjectURL(blob);
  let tmpImg = new Image();
  tmpImg.src = blobURL;
  tmpImg.width = svgClientW > svgW ? svgClientW : svgW;
  tmpImg.height = svgClientH > svgH ? svgClientH : svgH;

  tmpImg.onload = () => {
    let canvas = document.createElement("canvas");
    canvas.width = svgW;
    canvas.height = svgH;
    let context = canvas.getContext("2d");

    // draw blob img to canvas with some delay
    setTimeout(function () {
      context.drawImage(tmpImg, 0, 0, svgW, svgH);
      let pngDataUrl = canvas.toDataURL();
      let svgImg = document.createElement("img");
      svgImg.width = svgW;
      svgImg.height = svgH;
      svgImg.class = "svgImg";
      svgImg.src = pngDataUrl;
      // just additional wrapping for example usage
      let imgWrp = document.createElement("div");
      imgWrp.setAttribute("class", "img-wrp");
      imgWrp.appendChild(svgImg);
      document.body.appendChild(imgWrp);
    }, 300);
  };
}

    svg,
        img{
            border:1px solid #ccc
        }

        .svg-wrp{
            position:relative;
            overflow:auto;
            resize:both;
            width:50%;

        }

<div class="btn-wrp">
  <button type="button" onclick="svg2Png('svg')">svg2Png</button>
</div>

<div class="svg-wrp">

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 100">
<style>
@font-face {
    font-family: 'easyPrint';
     src: url('data:font/woff2;charset=utf-8;base64,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') format('woff2');
    font-weight: normal;
}
  </style>
  <text
    x="10"
    y="30"
    class="word"
    font-family="easyPrint"
    font-size="25"
  >
    TEST
  </text>
</svg>

</div>

3. Example: create svg with text rendered as path

This example employs the awesome opentype.js library.

Opentype.js has a handy function font.getPath() allowing you to render string as a svg <path> element based on the before loaded font file.

let svgcontainer = document.querySelector('#svgcontainer');
let inputText = document.querySelector('#inputText');
// opentype.js accepts only ttf and otf
let fontFile = 'https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf';
inputText.addEventListener('change', function(e) {
  let testString = e.currentTarget.value;
  let params = {
    string: testString,
    font: fontFile,
    fontSize: 100,
    x: 0,
    y: 0,
    decimals: 3
  }
  text2Path(params)
})

//default
let params = {
  string: inputText.value,
  font: fontFile,
  fontSize: 100,
  x: 0,
  y: 0,
  decimals: 3
}
text2Path(params)

function text2Path(params) {
  opentype.load(params.font, function(err, font) {
    if (!err) {
      let options = params.options;
      let path = font.getPath(params.string, params.x, params.fontSize, params.fontSize, options);
      let textPath = path.toSVG(params.decimals);
      let newSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      newSvg.classList.add('svgText');
      newSvg.setAttribute('xmlns', "http://www.w3.org/2000/svg");
      newSvg.insertAdjacentHTML('beforeend', textPath);
      svgcontainer.appendChild(newSvg);

      // adjust bbox
      let bb = newSvg.getBBox();
      newSvg.setAttribute('viewBox', '0 0 ' + (bb.width + bb.x) + ' ' + (params.fontSize * 1.5));

      //add downloadbtn
      let btnDownload = document.createElement("a");
      btnDownload.setAttribute('download', 'font-' + params.string + '.svg');
      btnDownload.textContent = 'Download';
      let dataURl = getDataUrl(newSvg.outerHTML, 'image/svg+xml');
      btnDownload.href = dataURl;
      svgcontainer.appendChild(btnDownload)

    } else {
      console.log('Font could not be loaded: ' + err);
    }
  });
}

function getDataUrl(str, mime) {
  let dataUrl = 'data:' + mime + ';base64,' + btoa(unescape(encodeURIComponent(str)))
  return dataUrl;
}

.svgText {
  height: 10em;
  display: inline-block;
  border: 1px solid #ccc;
}

a {
  display: block
}

<script src="https://cdn.jsdelivr.net/npm/opentype.js@latest/dist/opentype.min.js"></script>

<div class="layout">
  <div class="frm-wrp">
    <input id="inputText" type="text" value="Test">
  </div>
  <div class="svgcontainer" id="svgcontainer"></div>
</div>

Alternative: convert text to path in graphic editor

This is probably the most convenient solution.

Make sure the desired font is installed locally (in you OS).

Open your svg in an graphic editor like inkscape.

select you <text> elements and convert them to paths:

inkscape: Path / Object to path

Adobe Illustrator: Type / Create Outlines


来源: stackexchange

问:
Server-side options to deliver different page structure (HTML) to different mobile devices
I am researching best practices for developing 'classic' style mobile sites, i.e., mobile sites that are delivered and experienced as mobile HTML pages vs. small JavaScript applications (jQuery Mobile, Sencha, etc.).

There are two prevailing approaches:

Deliver the same page structure (HTML) to all mobile devices, then use CSS media queries or JavaScript to improve the experience for more capable devices.

Deliver an entirely different page structure (and possibly content) to devices with enhanced capabilities.

I'm specifically interested in best practices for the second approach. Two good examples are:

MIT's mobile site: different for Blackberries and feature(less) phones than for iOS & Android devices, but available at the same URLs -- http://m.mit.edu/

CNN's mobile site: ditto -- http://m.cnn.com/

I'd like to hear from people here at SO have actually worked on something like this, and can explain what the best practices are for delivering this type of device-dependent structure/content/experience.

I don't need a primer on mobile user-agent detection, or WURFL, or any of the concepts covered in other (great) SO threads like this one. I've used jQuery Mobile and Sencha Touch and I'm familiar with most approaches for delivering the final mobile experience, so no pointers required there either thanks.

What I really would like to understand is: how these specific types of experiences are delivered in terms of server-side detection and delivery based on user-agent groups -- where there's one stripped down page structure (different HTML) delivered to one group of devices, and another richer type of HTML document delivered to newer devices, but both at the same sub-domain / URLs.

Hope that all makes sense. Many thanks in advance.

答:
I have two examples for you.

Read up on how facebook achieves this using XHP to give abstract different output for different markups:  One Mobile Site to Serve Thousands of Phones

There will be a lot of good stuff in their actual implementation which I wish was available.

I use a framework called HawHaw, which let's you write your app once (in PHP Objects or XML files) and it outputs the correct markup to the device based on a few checks (accept header, agent string etc).

ContentLicense: CC BY-SA 3.0


问:
Update Text() based on user input in a TextFormField() within a form, perform a calculation and display results in another TextFormField()
I'm still new in Flutter, I'm trying to Update Text() based on user input in a TextFormField() within a form, perform two calculations and display results in other TextFormField() then POST the data to an API on pressing the Upload Button. I have tried using setState(){} as below but it's not working out.
'serviceFee' is supposed to be 2% of the 'amount' entered by the user then 'takeHome' is supposed to be 'amount' minus 'serviceFee'. Below is my code...

```<code>import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:keilvog/Screens/6kg_cylinder_screen.dart';
import 'package:keilvog/Widget/edit_image.dart';
import 'package:keilvog/Widget/header.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:http/http.dart' as http;
import 'package:keilvog/Widget/validators.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SellDetails extends StatefulWidget {
  const SellDetails({Key? key}) : super(key: key);

  @override
  State<SellDetails> createState() => _SellDetailsState();
}

class _SellDetailsState extends State<SellDetails> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final brandController = TextEditingController();
  final capacityController = TextEditingController();
  final amountController = TextEditingController();
  final serviceFeeController = TextEditingController();
  final takeHomeController = TextEditingController();
  File? image;

  bool isLoading = false;
  double _serviceFee = 0;
  // ignore: unused_field
  double _takeHome = 0;
  double amount = 0;

  Future UploadData({
    String? brand,
    String? capacity,
    double? amount,
    double? serviceFee,
    double? takeHome,
    File? image
  }) async
  {
    final SharedPreferences preferences = await SharedPreferences.getInstance();
    final String? myJWT = preferences.getString('jwt');
    Map<String, dynamic> token = jsonDecode(myJWT!);
    final myResponse = await http.post(
    Uri.parse('https://kelivog.com/sell/cylinder'),
    headers: <String, String>{
                'Content-Type': 'application/json; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Authorization': '$token',
                },

    body: jsonEncode(
      {
        'brand': brand,
        'capacity': capacity,
        'amount': amount,
        'serviceFee': serviceFee,
        'takeHome': takeHome,
        'image':'data:image/png;base64,' + base64Encode(image!.readAsBytesSync()),
      }),

    );
    return myResponse.statusCode;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(
          image: DecorationImage(
              image: AssetImage("images/background.jpg"), fit: BoxFit.cover)),
      child: Scaffold(
        // body: SingleChildScrollView(
        body: SingleChildScrollView(
          child: Column(
            children: [
              header(),
              SizedBox(height: 20.h),
              const EditImage(),
              SizedBox(height: 30.h),
              Container(
                width: 350.w,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(15.r)),
                  image: const DecorationImage(
                    image: AssetImage("images/background.jpg"),
                    fit: BoxFit.fitWidth,
                    alignment: Alignment.topCenter,
                  ),
                  boxShadow: const [
                    BoxShadow(color: Colors.grey, spreadRadius: 2),
                  ],
                ),
                child: Column(
                  children: [
                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("BRAND",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  //textAlignVertical: TextAlignVertical.center,
                                  validator: brandValidator,
                                  controller: brandController,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //const Divider(indent: 15, endIndent: 15, thickness: 2),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("CAPACITY",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  validator: capacityValidator,
                                  controller: capacityController,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("AMOUNT",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  validator: amountValidator,
                                  controller: amountController,
                                  keyboardType: TextInputType.number,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                  onChanged: (value) {
                                    setState(() {
                                      amount = value as double;
                                    });
                                  },
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("SERVICE FEE",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                //child: Text(serviceFeeController.text),
                                child: TextFormField(
                                  onChanged: (value) => setState(() {
                                    _serviceFee = value as double;
                                  }),
                                  // validator: ,
                                  // controller: ,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("TAKE HOME",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                //child: Text(serviceFeeController.text),
                                child: TextFormField(
                                  onChanged: (value) => setState(() {
                                    _takeHome = value as double;
                                  }),
                                  // validator: ,
                                  // controller: ,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    // rowItem('BRAND'),
                    // rowItem('CAPACITY'),
                    // rowItem('AMOUNT'),
                    // rowItem('SERVICE FEE'),
                    // rowItem('TAKE HOME'),
                  ],
                ),
              ),
              SizedBox(height: 40.h),
              ElevatedButton(
                onPressed: () async {
                  setState(() {
                    _serviceFee = (amount * 0.02);
                  });

                  setState(() {
                    _takeHome = amount - _serviceFee;
                  });
                  //final FormState? form = _formKey.currentState;
                  if (_formKey.currentState!.validate()){
                    if (image != null) {
                      await UploadData(
                        image: image,
                        brand: brandController.text,
                        capacity: capacityController.text,
                        amount: amountController.text as double,
                        serviceFee: serviceFeeController.text as double,
                        takeHome: takeHomeController.text as double
                      );
                    }
                    else
                    {
                      // ignore: avoid_print
                      print('You have not added an image');
                    }
                    if (isLoading) {
                      Navigator.pushReplacement(
                          context,
                          MaterialPageRoute(
                              builder: (context) =>
                                  const SixCylindersListsScreen(
                                    item: '', id: '', title: '',
                                  )));
                    } else {
                      throw Exception('Failed to upload details.');
                    }
                  }
                },
                child: Text(
                  'UPLOAD',
                  style: TextStyle(
                    color: Colors.yellow[600],
                    fontSize: 22.sp,
                    fontWeight: FontWeight.w700,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  elevation: 5,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(15.r),
                  ),
                  fixedSize: Size(150.w, 50.h),
                  primary: const Color(0xff261005),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

}

</code>```

答: use double.parse(value) to be able to assign value to the double declared values</p>

ContentLicense: CC BY-SA 4.0

Body:
I'm still new in Flutter, I'm trying to Update Text() based on user input in a TextFormField() within a form, perform two calculations and display results in other TextFormField() then POST the data to an API on pressing the Upload Button. I have tried using setState(){} as below but it's not working out.
'serviceFee' is supposed to be 2% of the 'amount' entered by the user then 'takeHome' is supposed to be 'amount' minus 'serviceFee'. Below is my code...

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:keilvog/Screens/6kg_cylinder_screen.dart';
import 'package:keilvog/Widget/edit_image.dart';
import 'package:keilvog/Widget/header.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:http/http.dart' as http;
import 'package:keilvog/Widget/validators.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SellDetails extends StatefulWidget {
  const SellDetails({Key? key}) : super(key: key);

  @override
  State<SellDetails> createState() => _SellDetailsState();
}

class _SellDetailsState extends State<SellDetails> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final brandController = TextEditingController();
  final capacityController = TextEditingController();
  final amountController = TextEditingController();
  final serviceFeeController = TextEditingController();
  final takeHomeController = TextEditingController();
  File? image;

  bool isLoading = false;
  double _serviceFee = 0;
  // ignore: unused_field
  double _takeHome = 0;
  double amount = 0;

  Future UploadData({
    String? brand,
    String? capacity,
    double? amount,
    double? serviceFee,
    double? takeHome,
    File? image
  }) async
  {
    final SharedPreferences preferences = await SharedPreferences.getInstance();
    final String? myJWT = preferences.getString('jwt');
    Map<String, dynamic> token = jsonDecode(myJWT!);
    final myResponse = await http.post(
    Uri.parse('https://kelivog.com/sell/cylinder'),
    headers: <String, String>{
                'Content-Type': 'application/json; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Authorization': '$token',
                },

    body: jsonEncode(
      {
        'brand': brand,
        'capacity': capacity,
        'amount': amount,
        'serviceFee': serviceFee,
        'takeHome': takeHome,
        'image':'data:image/png;base64,' + base64Encode(image!.readAsBytesSync()),
      }),

    );
    return myResponse.statusCode;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(
          image: DecorationImage(
              image: AssetImage("images/background.jpg"), fit: BoxFit.cover)),
      child: Scaffold(
        // body: SingleChildScrollView(
        body: SingleChildScrollView(
          child: Column(
            children: [
              header(),
              SizedBox(height: 20.h),
              const EditImage(),
              SizedBox(height: 30.h),
              Container(
                width: 350.w,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(15.r)),
                  image: const DecorationImage(
                    image: AssetImage("images/background.jpg"),
                    fit: BoxFit.fitWidth,
                    alignment: Alignment.topCenter,
                  ),
                  boxShadow: const [
                    BoxShadow(color: Colors.grey, spreadRadius: 2),
                  ],
                ),
                child: Column(
                  children: [
                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("BRAND",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  //textAlignVertical: TextAlignVertical.center,
                                  validator: brandValidator,
                                  controller: brandController,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //const Divider(indent: 15, endIndent: 15, thickness: 2),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("CAPACITY",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  validator: capacityValidator,
                                  controller: capacityController,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("AMOUNT",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                child: TextFormField(
                                  validator: amountValidator,
                                  controller: amountController,
                                  keyboardType: TextInputType.number,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                  onChanged: (value) {
                                    setState(() {
                                      amount = value as double;
                                    });
                                  },
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("SERVICE FEE",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                //child: Text(serviceFeeController.text),
                                child: TextFormField(
                                  onChanged: (value) => setState(() {
                                    _serviceFee = value as double;
                                  }),
                                  // validator: ,
                                  // controller: ,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),

                    Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 12.h, horizontal: 16.w),
                      child: Row(
                        children: [
                          Expanded(
                            child: Text("TAKE HOME",
                                style: TextStyle(
                                  fontSize: 18.sp,
                                  fontWeight: FontWeight.bold,
                                )),
                          ),
                          SizedBox(width: 1.w),
                          Expanded(
                            child: Container(
                              width: 90.w,
                              height: 40.h,
                              decoration: BoxDecoration(
                                  color: Colors.yellow[600],
                                  borderRadius: BorderRadius.circular(15)),
                              child: Center(
                                //child: Text(serviceFeeController.text),
                                child: TextFormField(
                                  onChanged: (value) => setState(() {
                                    _takeHome = value as double;
                                  }),
                                  // validator: ,
                                  // controller: ,
                                  showCursor: false,
                                  style: const TextStyle(
                                    fontSize: 20.0,
                                    height: 2.0,
                                    color: Colors.black,
                                  ),
                                  decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        top: 1.0, bottom: 100.0, left: 8.0),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(15.0)),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    // rowItem('BRAND'),
                    // rowItem('CAPACITY'),
                    // rowItem('AMOUNT'),
                    // rowItem('SERVICE FEE'),
                    // rowItem('TAKE HOME'),
                  ],
                ),
              ),
              SizedBox(height: 40.h),
              ElevatedButton(
                onPressed: () async {
                  setState(() {
                    _serviceFee = (amount * 0.02);
                  });

                  setState(() {
                    _takeHome = amount - _serviceFee;
                  });
                  //final FormState? form = _formKey.currentState;
                  if (_formKey.currentState!.validate()){
                    if (image != null) {
                      await UploadData(
                        image: image,
                        brand: brandController.text,
                        capacity: capacityController.text,
                        amount: amountController.text as double,
                        serviceFee: serviceFeeController.text as double,
                        takeHome: takeHomeController.text as double
                      );
                    }
                    else
                    {
                      // ignore: avoid_print
                      print('You have not added an image');
                    }
                    if (isLoading) {
                      Navigator.pushReplacement(
                          context,
                          MaterialPageRoute(
                              builder: (context) =>
                                  const SixCylindersListsScreen(
                                    item: '', id: '', title: '',
                                  )));
                    } else {
                      throw Exception('Failed to upload details.');
                    }
                  }
                },
                child: Text(
                  'UPLOAD',
                  style: TextStyle(
                    color: Colors.yellow[600],
                    fontSize: 22.sp,
                    fontWeight: FontWeight.w700,
                  ),
                ),
                style: ElevatedButton.styleFrom(
                  elevation: 5,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(15.r),
                  ),
                  fixedSize: Size(150.w, 50.h),
                  primary: const Color(0xff261005),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

}


问:
How to delete rows based on value of first column in matrix
I have a 3D matrix xyposframe and I would like to delete all rows in that matrix where the first column has a number below 150 or over 326. I tried the following but this didn't give me the desired result:

indexbelow = xyposframe(:, 1) < 150;
indexabove = xyposframe(:, 1) > 326;
xyposframe(indexbelow, :) = [];
xyposframe(indexabove, :) = [];
```

How can I delete those rows?

答:
The problem is that both indexbelow and indexabove are of size n -by- 1, i.e. column vectors with as much elements as there are rows in xyposframe. With xyposframe(indexbelow, :) = []; you remove a number of rows, thus making xyposframe have less than n rows, resulting in an error when you try to call xyposframe(indexabove, :) = [];, since you're attempting to index less than n elements with a total of n indices.

Possible solutions are to split the operation into two parts, or combine them in a single logical statement:

% First one, then the other
indexbelow = xyposframe(:, 1) < 150;
xyposframe(indexbelow, :) = [];
indexabove = xyposframe(:, 1) > 326;
xyposframe(indexabove, :) = [];

% Combine using logical AND
indexbelow = xyposframe(:, 1) < 150;
indexabove = xyposframe(:, 1) > 326;
xyposframe(indexbelow & indexabove, :) = [];

% Or put everything in a single indexing line using logical OR
xyposframe(xyposframe(:,1)<150 | xyposframe(:,1) > 326) = [];
```

Body:
I have a 3D matrix xyposframe and I would like to delete all rows in that matrix where the first column has a number below 150 or over 326. I tried the following but this didn't give me the desired result:

indexbelow = xyposframe(:, 1) < 150;
indexabove = xyposframe(:, 1) > 326;
xyposframe(indexbelow, :) = [];
xyposframe(indexabove, :) = [];

How can I delete those rows?


问:
React Native slow / freeze whet i call ethers.Wallet.fromMnemonic() [Ethers js 5.5.1]
when I call ethers.Wallet.fromMnemonic('....') my application freeze for 5/10 seconds and go next (is slow but work). If run application on emulator, work fine, but on android or ios I have this problem.
I tried to follow the docs on https://docs.ethers.io/v5/cookbook/react-native/ but i have the same problem

```<code>import "react-native-get-random-values"
import "@ethersproject/shims"
import { ethers } from "ethers";

const account = ethers.Wallet.fromMnemonic(mnemonic);
</code>```

答:
You can use ethereumjs-wallet, bip39 and ethers together to create a wallet.

import * as Bip39 from 'bip39';
import { Wallet } from 'ethers';
import { hdkey } from 'ethereumjs-wallet';

/**
 * @dev Create Wallet from Mnemonic
 * @param mnemonic = Mnemonic phrase
 * @param index  = Account index
 * @returns wallet
 */
const createWallet = async (mnemonic: string, index: number): Promise<Wallet> => {
  const seed = await Bip39.mnemonicToSeed(mnemonic);
  const hdNode = hdkey.fromMasterSeed(seed);
  const node = hdNode.derivePath(`m/44'/60'/0'`)
  // m/44'/60'/0'/0
  const change = node.deriveChild(0);
  // m/44'/60'/0'/0/{N}
  const childNode = change.deriveChild(index);
  const childWallet = childNode.getWallet();
  const wallet = new Wallet(childWallet.getPrivateKey().toString('hex'));
  return wallet
}
```
<p>I have test this in both IOS and Android and was able to create a HD Wallet instantly.</p>
<p>To use <code>bip39</code> in <code>React Native</code>  environment you have to apply some patches to <code>bip39</code>.
You can refer how MetaMask mobile-app has applied those patches here using <code>patch-package</code>.
In my patch I have imported <code>randomBytes</code> from <code>react-native-crypto</code> instead of <code>randombytes</code> module</p>
<pre class="lang-js prettyprint-override"><code>var {randomBytes} = require('react-native-crypto')
</code>```

Versions of node modules I have used,

```<code>bip39 = 2.6.0
ethers = 5.5.3
ethereumjs-wallet = 1.0.2
react-native-crypto = 2.2.0
</code>```

Body:
when I call ethers.Wallet.fromMnemonic('....') my application freeze for 5/10 seconds and go next (is slow but work). If run application on emulator, work fine, but on android or ios I have this problem.
I tried to follow the docs on https://docs.ethers.io/v5/cookbook/react-native/ but i have the same problem

import "react-native-get-random-values"
import "@ethersproject/shims"
import { ethers } from "ethers";

const account = ethers.Wallet.fromMnemonic(mnemonic);

Body:
You can use ethereumjs-wallet, bip39 and ethers together to create a wallet.

import * as Bip39 from 'bip39';
import { Wallet } from 'ethers';
import { hdkey } from 'ethereumjs-wallet';

/**
 * @dev Create Wallet from Mnemonic
 * @param mnemonic = Mnemonic phrase
 * @param index  = Account index
 * @returns wallet
 */
const createWallet = async (mnemonic: string, index: number): Promise<Wallet> => {
  const seed = await Bip39.mnemonicToSeed(mnemonic);
  const hdNode = hdkey.fromMasterSeed(seed);
  const node = hdNode.derivePath(`m/44'/60'/0'`)
  // m/44'/60'/0'/0
  const change = node.deriveChild(0);
  // m/44'/60'/0'/0/{N}
  const childNode = change.deriveChild(index);
  const childWallet = childNode.getWallet();
  const wallet = new Wallet(childWallet.getPrivateKey().toString('hex'));
  return wallet
}

I have test this in both IOS and Android and was able to create a HD Wallet instantly.

To use bip39 in React Native  environment you have to apply some patches to bip39.
You can refer how MetaMask mobile-app has applied those patches here using patch-package.
In my patch I have imported randomBytes from react-native-crypto instead of randombytes module

var {randomBytes} = require('react-native-crypto')

Versions of node modules I have used,

bip39 = 2.6.0
ethers = 5.5.3
ethereumjs-wallet = 1.0.2
react-native-crypto = 2.2.0


问:
R barplot axis scaling
I want to plot a barplot of some data with some x-axis labels but so far I just keep running into the same problem, as the axis scaling is completely off limits and therefore my labels are wrongly positioned below the bars.
The most simple example I can think of:

```<code>x = c(1:81)
barplot(x)
axis(side=1,at=c(0,20,40,60,80),labels=c(20,40,60,80,100))
</code>```

As you can see, the x-axis does not stretch along the whole plot but stops somewhere in between. It seems to me as if the problem is quite simple, but I somehow I am not able to fix it and I could not find any solution so far :(

Any help is greatly appreciated.

答:
I run into the same annoying property of batplots - the x coordinates go wild. I would add one another way to show the problem, and that is adding more lines to the plot.

```<code>x = c(1:81)
barplot(x)
axis(side=1,at=c(0,20,40,60,80),labels=c(20,40,60,80,100))
lines(c(81,81), c(0, 100)) # this should cross the last bar, but it does not
</code>```

The best I came with was to define a new barplot function that will take also the parameter "at" for plotting positions of the bars.

```<code>barplot_xscaled <- function(bar_heights, at = NA, width = 0.5, col = 'grey'){
  if ( is.na(at) ){
    at <- c(1:length(bar_heights))
  }

  plot(bar_heights, type="n", xlab="", ylab="",
       ylim=c(0, max(bar_heights)), xlim=range(at), bty = 'n')
  for ( i in 1:length(bar_heights)){
    rect(at[i] - width, 0, at[i] + width, bar_heights[i], col = col)
  }
}

barplot_xscaled(x)
lines(c(81, 81), c(0, 100))
</code>```

The lines command crosses the last bar - the x scale works just as naively expected, but you could also now define whatever positions of the bars you would like (you could play more with the function a bit to have the same properties as other R plotting functions).

Title: R barplot axis scaling

Body:
I want to plot a barplot of some data with some x-axis labels but so far I just keep running into the same problem, as the axis scaling is completely off limits and therefore my labels are wrongly positioned below the bars.
The most simple example I can think of:

x = c(1:81)
barplot(x)
axis(side=1,at=c(0,20,40,60,80),labels=c(20,40,60,80,100))

As you can see, the x-axis does not stretch along the whole plot but stops somewhere in between. It seems to me as if the problem is quite simple, but I somehow I am not able to fix it and I could not find any solution so far :(

Any help is greatly appreciated.

Body:
I run into the same annoying property of batplots - the x coordinates go wild. I would add one another way to show the problem, and that is adding more lines to the plot.

x = c(1:81)
barplot(x)
axis(side=1,at=c(0,20,40,60,80),labels=c(20,40,60,80,100))
lines(c(81,81), c(0, 100)) # this should cross the last bar, but it does not

The best I came with was to define a new barplot function that will take also the parameter "at" for plotting positions of the bars.

barplot_xscaled <- function(bar_heights, at = NA, width = 0.5, col = 'grey'){
  if ( is.na(at) ){
    at <- c(1:length(bar_heights))
  }

  plot(bar_heights, type="n", xlab="", ylab="",
       ylim=c(0, max(bar_heights)), xlim=range(at), bty = 'n')
  for ( i in 1:length(bar_heights)){
    rect(at[i] - width, 0, at[i] + width, bar_heights[i], col = col)
  }
}

barplot_xscaled(x)
lines(c(81, 81), c(0, 100))

The lines command crosses the last bar - the x scale works just as naively expected, but you could also now define whatever positions of the bars you would like (you could play more with the function a bit to have the same properties as other R plotting functions).


问:
Can I rotate place(s) names with the "transform rotate" css on my google map (api)?
I am rotating my google map on my mobile internet page with the following with inline css;

```<code><div id="map" style="transform:rotate(45deg); -ms-
transform:rotate(45deg); /* IE 9 */ -moz-transform:rotate(45deg);
/* Firefox */ -webkit-transform:rotate(45deg); /* Safari and Chrome
 */ -o-transform:rotate(45deg); /* Opera */"></div>
</code>```

That works fine. But I am also using "places" to show googles customer locations like restaurants etc. The names show up fine, but they also rotate 45 degrees. That would mean that when I rotate to 180 degrees, the names would be upside down.

I can't find code to keep the names horizontal at 0 degrees (or 360) to keep them readable.
I tried rotation with tilt and 90/180/270 degrees, but it doesn't always work and
the map has to be in satelite mode for that.

On the official google map app on mobile phones, rotate works with two fingers and the
place names stay horizontal. I wish I could do that programmatically.

But for now I would be happy to just keep the places-names horizontal.

Any idea's ?

答:
I found the answer. I am now using a different google map type namely "vector" i.o. the default "raster" together with a map-id.
It's slightly slower, but I can turn the map with two fingers on a phone and change the heading degrees to any value (0-360).</p>

Body:
I am rotating my google map on my mobile internet page with the following with inline css;

That works fine. But I am also using "places" to show googles customer locations like restaurants etc. The names show up fine, but they also rotate 45 degrees. That would mean that when I rotate to 180 degrees, the names would be upside down.

I can't find code to keep the names horizontal at 0 degrees (or 360) to keep them readable.
I tried rotation with tilt and 90/180/270 degrees, but it doesn't always work and
the map has to be in satelite mode for that.

On the official google map app on mobile phones, rotate works with two fingers and the
place names stay horizontal. I wish I could do that programmatically.

But for now I would be happy to just keep the places-names horizontal.

Any idea's ?


问:
What context does the scheduler code run in?
There are two cases where the scheduler code schedule() is invoked-

When a process voluntarily calls schedule()

Timer interrupt calls schedule()

In case 2, I think schedule() runs in interrupt context, but what about the first case? Does it run in the context of the process which invoked it?

Also are there any more scenarios which invoke schedule()?

答: schedule() always runs in process context.  In the second case, when it is initiated by a timer interrupt, it is in the return path back from the kernel to the interrupted process where schedule() is called.


问:
How to detect when the user has scrolled to a certain area on the page using JavaScript? and then run an animation?
How to detect when the user has scrolled to a certain area on the page using JavaScript? and then run an animation?
I need to run animation when scrolled to that section please help if you know any part of the problem.</p>

答: If it doesn't have to be in Vanilla Javascript You could look at this library https://greensock.com/scrolltrigger/</p>


问:
How to remove the select all option from a v-data-table?
I need to hide the select all option from a v-data-table, the vuetify component. According to the documentation including the header-prop, single-select as true should do it but is not working.</p>
```<code><v-data-table
v-model="selected
:headers="headers"
:items="items"
show-select
:header-props="{singleSelect:true}"
></v-data-table>
</code>```

答:
If you want to be able to only select one item at a time you can add single-select directly to v-data-table:

<v-data-table
  v-model="selected"
  :headers="headers"
  :items="items"
  show-select
  single-select
></v-data-table>
```
<p>If you want to be able to select <strong>multiple items</strong> you can override the select all checkbox with the <code>header.data-table-select</code> slot:</p>
<pre class="lang-html prettyprint-override"><code><v-data-table
  v-model="selected"
  :headers="headers"
  :items="items"
  show-select
>
  <template #header.data-table-select></template>
</v-data-table>
</code>```

Body:
I need to hide the select all option from a v-data-table, the vuetify component. According to the documentation including the header-prop, single-select as true should do it but is not working.

<v-data-table
v-model="selected
:headers="headers"
:items="items"
show-select
:header-props="{singleSelect:true}"
></v-data-table>

Body:
If you want to be able to only select one item at a time you can add single-select directly to v-data-table:

<v-data-table
  v-model="selected"
  :headers="headers"
  :items="items"
  show-select
  single-select
></v-data-table>

If you want to be able to select multiple items you can override the select all checkbox with the header.data-table-select slot:

<v-data-table
  v-model="selected"
  :headers="headers"
  :items="items"
  show-select
>
  <template #header.data-table-select></template>
</v-data-table>


问:
Set custom Customer attribute value programmatically Magento 2
I am importing some customers with :

```<code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        $customerFactory = $objectManager->create('\Magento\Customer\Model\CustomerFactory');

        $customer = $objectManager->create('Magento\Customer\Model\Customer')->setWebsiteId(1)->loadByEmail('customrr@custom.com');

        try {
            if(!empty($customer->getData('email')))
            {
                $customer->setAttr1(1); // Attr1 = Name of the custom Attribute
                $customer->setAttr2(2); // Attr2 = Name of the custom Attribute
            }
            else
            {
                $customer = $customerFactory->create()->setWebsiteId(1);
            }

            $customer->setLastname("Lastname");

            $customer->setFirstname("Firsty");

            .....

            $customer->save();
</code>```

The customer is saved with all his standard attributes correctly but my new attributes won't be saved anyway.  I've also tried :

```<code>$customer->setCustomAttribute('Attr1','value');
</code>```

but this didn't work too.

The custom Attribute are shown correclty in Magentos 2 backoffice and the values are saved correctly too if creating a customer manually.

答:
```<code><?php

namespace Custom\Module\Setup;

use Magento\Eav\Model\Config;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;

    public function __construct(
        EavSetupFactory $eavSetupFactory,
        Config $eavConfig
    ) {
        $this->eavSetupFactory = $eavSetupFactory;
        $this->eavConfig = $eavConfig;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        $eavSetup->addAttribute(\Magento\Customer\Model\Customer::ENTITY, 'custom_attribute', [
                'label' => 'Label',
                'system' => 0,
                'position' => 720,
                'sort_order' => 720,
                'visible' => true,
                'note' => '',
                'type' => 'int',
                'input' => 'boolean',
                'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
                'backend' => \Custom\Module\Model\Customer\Attribute\Backend\DoWHatEver::class,
            ]
        );

        $attribute = $this->getEavConfig()->getAttribute(\Magento\Customer\Model\Customer::ENTITY, 'custom_attribute');
        $attribute->addData([
                'is_user_defined' => 1,
                'is_required' => 0,
                'default_value' => 0,
                'used_in_forms', ['adminhtml_customer']
            ])->save();
    }

    public function getEavConfig()
    {
        return $this->eavConfig;
    }
}
</code>```

Body:
I am importing some customers with :

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        $customerFactory = $objectManager->create('\Magento\Customer\Model\CustomerFactory');

        $customer = $objectManager->create('Magento\Customer\Model\Customer')->setWebsiteId(1)->loadByEmail('customrr@custom.com');

        try {
            if(!empty($customer->getData('email')))
            {
                $customer->setAttr1(1); // Attr1 = Name of the custom Attribute
                $customer->setAttr2(2); // Attr2 = Name of the custom Attribute
            }
            else
            {
                $customer = $customerFactory->create()->setWebsiteId(1);
            }

            $customer->setLastname("Lastname");

            $customer->setFirstname("Firsty");

            .....

            $customer->save();

The customer is saved with all his standard attributes correctly but my new attributes won't be saved anyway.  I've also tried :

$customer->setCustomAttribute('Attr1','value');

but this didn't work too.

The custom Attribute are shown correclty in Magentos 2 backoffice and the values are saved correctly too if creating a customer manually.


问:
Issue Related to repetition of button in form React Native
I am creating a Questionnaire in ReactNative, when fetching data from firebase and displaying it the submit button is coming after each Question. I want the button to be displayed at the end if I remove the button from the  tag and put it in another  tag then it displays one time, but the forms do not get submitted. The Problem occurs after the second return in the code.
My code is:</p>
```<code>./DetailsScreen

import './App.css';
import firebase from './firebase';
import React,{useState,useEffect} from 'react';
import { RadioButton } from 'react-native-paper';
import { storage } from "./firebase";
import logo from "./assets/front.png";
const DetailsScreen = ({ navigation }) => {
  const [QuestionD, setQuestionD] = useState("");
  const [choice1, setchoice1] = useState("");
  const [choice2, setchoice2] = useState("");
  const [message, setMessage] = useState("");
  const [image, setImage] = useState(null);
  const [url, setUrl] = useState("");
  const [progress, setProgress] = useState(0);
  const [error, setError] = useState("");

  const handChange = e => {
    const file = e.target.files[0];
    if (file) {
      const fileType = file["type"];
      const validImageTypes = ["image/gif", "image/jpeg", "image/jpg","image/png"];
      if (validImageTypes.includes(fileType)) {
        setError("");
        setImage(file);
      } else {
        setError("Please select an image to upload");
      }
    }
  };

  const handleUpdate = () => {
    if (image) {
      const uploadTask = storage.ref(`images/${image.name}`).put(image);

      uploadTask.on(
        "state_changed",
        snapshot => {
          const progress = Math.round(
            (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          );
          setProgress(progress);
        },
        error => {
          setError(error);
        },
        () => {
          storage
            .ref("images")
            .child(image.name)
            .getDownloadURL()
            .then(url => {
              setUrl(url);
              setProgress(0);
            });
        }
      );
    } else {
      setError("Error please choose an image to upload");
    }
  };

  const [loader, setLoader] = useState(false);

   const handleSubmit = (e) => {
        e.preventDefault();
        setLoader(true);
  firebase.firestore().collection("Response")
  .add({
            choice1:choice1,
            choice2:choice2,
            message : message,
            QuestionD:QuestionD,
            timestamp : firebase.firestore.FieldValue.serverTimestamp(),

          })
          .then(() => {
            setLoader(false);
            alert("Your form has been submitted");
          })
          .catch((error) => {
            alert(error.message);
            setLoader(false);
          });

        setchoice1("");
        setchoice2("");
        setQuestionD("");
        setMessage("");
         };
  const [books, setBooks] = useState([]);
  useEffect(() => {
    getBooks();
  }, []);
  const getBooks = async () => {
    var random = Math.floor((Math.random() *  100) + 1)
    const response=firebase.firestore().collection('Humemah')
    .where("ID",">=" , random)
    .limit(10)
    const data=await response.get();

    console.log(data.docs);
    setBooks(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
  };

  return (
    <div className="header">
    <h1>QUESTIONNAIRE</h1>
    {
     books.map((doc, index) => {
    return(
      <form className="Question" onSubmit={handleSubmit}>

        <label className='fields' onsubmit={(e) => setQuestionD(e.target.value)} value={doc.QuestionD}>QUESTION: {String(doc.QuestionD)}
        </label>

        <br>
        </br>

       <div>
        <label className='fields' >YES</label>
        <input type="radio" id value={doc.Choice1} onsubmit={(e) => setchoice1(e.target.value)}/>
        </div>
        <br></br>
        <div >
        <label className='fields'>NO</label>
        <input type="radio"  value={doc.Choice2} onChange={(e) => setchoice2(e.target.value)}/>
        </div>
        <br></br>
        <div className='fields'>
        <label className='box'> MESSAGE: </label> </div>
          <textarea
            placeholder="Message"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
          ></textarea>

  <br></br>
  <div>
      <div>
        <input type="file" onChange={handChange} />{" "}
        <button onClick={handleUpdate}> UPLOAD </button>
      </div>
      <div style={{ height: "20px" }}>
        {progress > 0 ? <progress value={progress} max="20" /> : ""}
        <p style={{ color: "red" }}>{error}</p>
      </div>
      <div className='fields'>
      {url ? (
        <img src={url} width='150' height=' 150' />
      ) : (
        <img  width='100' height=' 100' />
      )}
      </div>
    </div>
    <div className='button'>
    <button type="submit" > SUMBIT </button>
    </div>
    </form>
    )
    })
    }
    </div>
    );
}
export default DetailsScreen;
</code>```

答:
Submit button is working only inside form tag right, so don't change submit button to another tag instead show submit button only in last element by comparing books array length and item index like shown below</p>
```<code>{(index == (books.length - 1)) && <button type="submit" > SUMBIT </button>}
</code>```

Body:
I am creating a Questionnaire in ReactNative, when fetching data from firebase and displaying it the submit button is coming after each Question. I want the button to be displayed at the end if I remove the button from the  tag and put it in another  tag then it displays one time, but the forms do not get submitted. The Problem occurs after the second return in the code.
My code is:

./DetailsScreen

import './App.css';
import firebase from './firebase';
import React,{useState,useEffect} from 'react';
import { RadioButton } from 'react-native-paper';
import { storage } from "./firebase";
import logo from "./assets/front.png";
const DetailsScreen = ({ navigation }) => {
  const [QuestionD, setQuestionD] = useState("");
  const [choice1, setchoice1] = useState("");
  const [choice2, setchoice2] = useState("");
  const [message, setMessage] = useState("");
  const [image, setImage] = useState(null);
  const [url, setUrl] = useState("");
  const [progress, setProgress] = useState(0);
  const [error, setError] = useState("");

  const handChange = e => {
    const file = e.target.files[0];
    if (file) {
      const fileType = file["type"];
      const validImageTypes = ["image/gif", "image/jpeg", "image/jpg","image/png"];
      if (validImageTypes.includes(fileType)) {
        setError("");
        setImage(file);
      } else {
        setError("Please select an image to upload");
      }
    }
  };

  const handleUpdate = () => {
    if (image) {
      const uploadTask = storage.ref(`images/${image.name}`).put(image);

      uploadTask.on(
        "state_changed",
        snapshot => {
          const progress = Math.round(
            (snapshot.bytesTransferred / snapshot.totalBytes) * 100
          );
          setProgress(progress);
        },
        error => {
          setError(error);
        },
        () => {
          storage
            .ref("images")
            .child(image.name)
            .getDownloadURL()
            .then(url => {
              setUrl(url);
              setProgress(0);
            });
        }
      );
    } else {
      setError("Error please choose an image to upload");
    }
  };

  const [loader, setLoader] = useState(false);

   const handleSubmit = (e) => {
        e.preventDefault();
        setLoader(true);
  firebase.firestore().collection("Response")
  .add({
            choice1:choice1,
            choice2:choice2,
            message : message,
            QuestionD:QuestionD,
            timestamp : firebase.firestore.FieldValue.serverTimestamp(),

          })
          .then(() => {
            setLoader(false);
            alert("Your form has been submitted");
          })
          .catch((error) => {
            alert(error.message);
            setLoader(false);
          });

        setchoice1("");
        setchoice2("");
        setQuestionD("");
        setMessage("");
         };
  const [books, setBooks] = useState([]);
  useEffect(() => {
    getBooks();
  }, []);
  const getBooks = async () => {
    var random = Math.floor((Math.random() *  100) + 1)
    const response=firebase.firestore().collection('Humemah')
    .where("ID",">=" , random)
    .limit(10)
    const data=await response.get();

    console.log(data.docs);
    setBooks(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
  };

  return (

QUESTIONNAIRE

    {
     books.map((doc, index) => {
    return(
      <form className="Question" onSubmit={handleSubmit}>

         setQuestionD(e.target.value)} value={doc.QuestionD}>QUESTION: {String(doc.QuestionD)}

        YES
        <input type="radio" id value={doc.Choice1} onsubmit={(e) => setchoice1(e.target.value)}/>

        NO
        <input type="radio"  value={doc.Choice2} onChange={(e) => setchoice2(e.target.value)}/>

         MESSAGE:

          <textarea
            placeholder="Message"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
          ></textarea>

        <input type="file" onChange={handChange} />{" "}
        <button onClick={handleUpdate}> UPLOAD </button>

        {progress > 0 ? <progress value={progress} max="20" /> : ""}

{error}

      {url ? (

      ) : (

      )}

    <button type="submit" > SUMBIT </button>

    </form>
    )
    })
    }

    );
}
export default DetailsScreen;

Body:
Submit button is working only inside form tag right, so don't change submit button to another tag instead show submit button only in last element by comparing books array length and item index like shown below

{(index == (books.length - 1)) && <button type="submit" > SUMBIT </button>}


问:
In Colab : Reading / Watching logs as they grow
In Python, if you use the logging module, you can configure it to write the logs to stdout/console, a file, etc.

The problem is that you may want to monitor the logs without blocking the execution of other things. You want to see them grow, while you run other things.

In Linux you typically open another console and use
# tail -f file.log
and watch it grow, even with color adding other tools to the mix.

In Colab ... that is not so easy.

I'll dump here a few ideas so the question can be found and better answers may be added.

You could:

run a tiny web server so the file.log can be accessed from a browser.
Problem: it doesn't grow/update with new content. There are workarounds for that, but they look ugly.

cat the file.log into a netcat connection connected to ngrok, and from your local machine use netcat (nc) to read that pipe

open a ssh into Colab and do the tail -f file.log just as you used to do.

send them to AWS Cloudwatch and maybe retrieve them on real-time for inspection

QUESTION: What is your preferred way to read the logs produced within Colab ( read inside and/or outside Colab )

答:
open a ssh into Colab and do the tail -f file.log just as you used to
do.

This option is very comfortable as you can resize your local console window and move it around, being it outside Colab.

Thanks to some people, nowadays is really easy to get there.

Run this on a cell. Code comes from here.

```<code># Install colab_ssh
!pip install colab_ssh --upgrade

from colab_ssh import launch_ssh
launch_ssh('YOUR_NGROK_AUTH_TOKEN', 'SOME_PASSWORD')
</code>```

This will output something like (as of 2022-02-10)

```<code>Collecting colab_ssh
  Downloading colab_ssh-0.3.27-py3-none-any.whl (26 kB)
Installing collected packages: colab-ssh
Successfully installed colab-ssh-0.3.27
Warning: Due to some issues with ngrok on Google Colab, reported in the issue https://github.com/WassimBenzarti/colab-ssh/issues/45,
we highly recommend that update your code by following this documentation https://github.com/WassimBenzarti/colab-ssh#getting-started
Successfully running X.tcp.ngrok.io:12345
[Optional] You can also connect with VSCode SSH Remote extension using this configuration:

  Host google_colab_ssh
    HostName X.tcp.ngrok.io
    User root
    Port 12345

</code>```

Now, on your local machine (or wherever you want) open a console and type.

ssh  -p 12345   root@X.tcp.ngrok.io

After that you are INSIDE Colab and you can do.

tail -f /content/file.log

And watch it grow.

After some inactivity the connection may get closed.

Because the host changes frequently, using RSA keys to avoid typing the password doesn't seem like a good solution.

So you may want to install sshpass

```<code># sudo apt-get install sshpass
</code>```

So you can simply reuse the command for connection after getting disconnected

```<code># sshpass -p <PASSWORD> ssh -p <PORT>  root@X.tcp.ngrok.io
</code>```

Body:
open a ssh into Colab and do the tail -f file.log just as you used to
do.

This option is very comfortable as you can resize your local console window and move it around, being it outside Colab.

Thanks to some people, nowadays is really easy to get there.

Run this on a cell. Code comes from here.

# Install colab_ssh
!pip install colab_ssh --upgrade

from colab_ssh import launch_ssh
launch_ssh('YOUR_NGROK_AUTH_TOKEN', 'SOME_PASSWORD')

This will output something like (as of 2022-02-10)

Collecting colab_ssh
  Downloading colab_ssh-0.3.27-py3-none-any.whl (26 kB)
Installing collected packages: colab-ssh
Successfully installed colab-ssh-0.3.27
Warning: Due to some issues with ngrok on Google Colab, reported in the issue https://github.com/WassimBenzarti/colab-ssh/issues/45,
we highly recommend that update your code by following this documentation https://github.com/WassimBenzarti/colab-ssh#getting-started
Successfully running X.tcp.ngrok.io:12345
[Optional] You can also connect with VSCode SSH Remote extension using this configuration:

  Host google_colab_ssh
    HostName X.tcp.ngrok.io
    User root
    Port 12345

Now, on your local machine (or wherever you want) open a console and type.

ssh  -p 12345   root@X.tcp.ngrok.io

After that you are INSIDE Colab and you can do.

tail -f /content/file.log

And watch it grow.

After some inactivity the connection may get closed.

Because the host changes frequently, using RSA keys to avoid typing the password doesn't seem like a good solution.

So you may want to install sshpass

# sudo apt-get install sshpass

So you can simply reuse the command for connection after getting disconnected

# sshpass -p <PASSWORD> ssh -p <PORT>  root@X.tcp.ngrok.io


问:
Global Object in singleton
In the Singleton pattern why is that we have to use a static object and not a global object?

I tried the following

```<code>class Singleton;
Singleton*  instance1 = NULL;

class Singleton
{
private :
       Singleton()
       {
       }
       //static Singleton* instance1;

public:
        static Singleton* getinstance()

 if(instance1== NULL)
       {
       instance1 = new Singleton();
       }

 return instance1;

 void Dispaly()
       {
       }
 ~Singleton()
       {
       }
};
</code>```

When I compile this code I get the error "multiple definition of instance1"

Can anyone please give a plausible reason for this?

答:
Put the definition of instance1 in a cpp file and an extern in the header.

It would be more typical to use a static class member though, as you have commented out.
You just need to define it in a cpp file:

```<code>Singleton* Singleton::instance1 = 0;
</code>```

Title: Global Object in singleton

Body:
In the Singleton pattern why is that we have to use a static object and not a global object?

I tried the following

class Singleton;
Singleton*  instance1 = NULL;

class Singleton
{
private :
       Singleton()
       {
       }
       //static Singleton* instance1;

public:
        static Singleton* getinstance()

 if(instance1== NULL)
       {
       instance1 = new Singleton();
       }

 return instance1;

 void Dispaly()
       {
       }
 ~Singleton()
       {
       }
};

When I compile this code I get the error "multiple definition of instance1"

Can anyone please give a plausible reason for this?

Body:
Put the definition of instance1 in a cpp file and an extern in the header.

It would be more typical to use a static class member though, as you have commented out.
You just need to define it in a cpp file:

Singleton* Singleton::instance1 = 0;